# Rebasely docs > Rebasely is git hosting for people and agents working together, on Cloudflare: every repository is its own Durable Object, with pull requests, Actions on Cloudflare Sandboxes, live branches, sandboxes, agent identities with approvals, and an MCP server. # Rebasely docs Rebasely is git hosting for people and agents working together. Every repository is its own Durable Object on Cloudflare, with pull requests, Actions, live branches, sandboxes and an MCP server. This guide covers all of it, from the first push to agents that ask for approval. ```sh curl -fsSL https://rebasely.com/install | sh rebasely auth login ``` ## Start here From an account to your first push, and the questions people ask first. 1. [Getting started](https://rebasely.com/docs/start): Sign up, install the Rebasely CLI, sign git in with an access token, and push your first commit to Rebasely. 2. [FAQ](https://rebasely.com/docs/faq): Short answers about Rebasely: what it is, what it costs, how it differs from other git hosts, and what is still in beta. ## Work with people and agents Review, edit together, try things in a sandbox, and let tools work under their own name. 1. [Pull requests](https://rebasely.com/docs/pull-requests): Open, review and merge pull requests on Rebasely from the web, the CLI, the API or an agent, with the Visual diff of the architecture, protected branches and checks. 2. [Live branches and mount](https://rebasely.com/docs/live): Edit one branch together with people and agents: mount it as a folder with rebasely mount, and Rebasely commits checkpoints as you go. 3. [Sandboxes](https://rebasely.com/docs/sandboxes): Give each task its own hidden branch: create a sandbox from any commit, run its checks and merge it back with one command. 4. [Agents and approvals](https://rebasely.com/docs/agents): Give each automated tool its own identity, token and limits in an organization, and let it ask an owner to approve what only an owner may do. 5. [SSH (turned off)](https://rebasely.com/docs/ssh): Rebasely no longer offers git over SSH. How to clone and push over HTTPS instead, and switch an existing clone. ## Understand how it fits together What happens on a push, and the folder that describes your system. 1. [How Rebasely works](https://rebasely.com/docs/how-it-works): What happens when you push to Rebasely: the Worker, the repository's own Durable Object, and where your objects are stored. 2. [The .rebasely folder](https://rebasely.com/docs/dot-rebasely): Keep a knowledge base, an architecture map, dataflows and Actions workflows in a .rebasely folder, so people and agents work from the same context as the code. ## Run CI Workflows in .rebasely/workflows, each job in its own sandbox. 1. [Actions](https://rebasely.com/docs/actions): Run CI on every push and pull request with Rebasely Actions: workflows in .rebasely/workflows, jobs on Cloudflare Sandboxes, logs, secrets and checks. 2. [Workflow syntax](https://rebasely.com/docs/workflow-syntax): The keys of a Rebasely Actions workflow file: triggers, jobs, steps, expressions, built-in actions and the variables a step sees. ## Look something up Commands, endpoints, tools, limits and errors. 1. [CLI reference](https://rebasely.com/docs/cli): Every rebasely command and flag, generated from the CLI's own help: pull requests, sandboxes, Actions runs, mounts, agents and sign-in. 2. [REST API](https://rebasely.com/docs/api): The Rebasely REST API under /api/v1: authentication with access tokens, errors, and the endpoints for repositories, pull requests, sandboxes, live branches and Actions. 3. [MCP server](https://rebasely.com/docs/mcp): Connect agents to Rebasely over the Model Context Protocol, at /mcp or through rebasely mcp, and the tools they get. 4. [Limits](https://rebasely.com/docs/limits): Every limit Rebasely enforces in one place: repository size, pushes, pull requests, live edits, sandboxes, agents and Actions. 5. [Push errors](https://rebasely.com/docs/errors): What each error from a push to Rebasely means and how to fix it, from size limits to protected branches. 6. [Git LFS](https://rebasely.com/docs/lfs): Rebasely does not store Git LFS objects yet. What to do with large files until it does. ## Keep your account safe Signing in, confirming it's you, and access tokens. 1. [Sign-in and passkeys](https://rebasely.com/docs/sign-in): How you sign in to Rebasely with Google, why passkeys are optional, and how Rebasely asks you to confirm it's you before sensitive actions. 2. [Access tokens](https://rebasely.com/docs/tokens): Personal and agent access tokens: their scopes, expiry, tokens for all your organizations, where git and the CLI keep them, and what happens when one leaks into a push. For tools and agents: [/llms.txt](https://rebasely.com/llms.txt) lists every page, [/llms-full.txt](https://rebasely.com/llms-full.txt) has all of them in one file, and each page is Markdown at its address plus `.md`. Coding agents also get the [Rebasely agent skill](https://rebasely.com/docs/skills/rebasely/SKILL.md). --- Source: https://rebasely.com/docs # Getting started From signing up to your first push in a few minutes, then on to what makes Rebasely different: live branches, sandboxes and agents. ### 1. Create your account Sign up with Google and accept the terms. Rebasely lets a limited number of new people in each day; if today's places are taken, you join the waitlist and get an email when yours opens. [Sign up with Google](https://rebasely.com/signin?return_to=%2Fdocs%2Fstart) Before sensitive actions, such as creating an access token or making a repository public, Rebasely asks you to confirm it's you with Google or a passkey. Passkeys are optional: [how sign-in works](https://rebasely.com/docs/sign-in). ### 2. Create an organization and a repository Every repository belongs to an organization, which can be just you. Create an organization, then a repository, from your home page. New repositories are private; an owner can make one public in its settings. ### 3. Install the CLI The Rebasely CLI is one file and needs Node.js 22.18 or later. macOS and Linux: ```sh curl -fsSL https://rebasely.com/install | sh ``` Windows: ```sh # in WSL (Windows Subsystem for Linux) curl -fsSL https://rebasely.com/install | sh ``` The installer puts the CLI in `~/.rebasely` and the `rebasely` command on your PATH, with `duragit` as an alias; it is short, so [read it](https://rebasely.com/install) first if you like. Run it again to update. ### 4. Sign git in The CLI asks you to approve an access token in your browser and hands it to git's credential helper, so `git push` just works. HTTPS: ```sh rebasely auth login ``` Without the CLI: ```sh # Create a token with the repo:write scope at /settings/tokens, # then paste it when git asks for a password. git push ``` `rebasely auth status` shows what is signed in. [Access tokens](https://rebasely.com/docs/tokens) has the details. SSH access is turned off. ### 5. Push From a repository you already have: ```sh git remote add origin https://rebasely.com//.git git push -u origin HEAD ``` Or start a new one: ```sh mkdir app && cd app git init -b main echo "# app" > README.md git add README.md && git commit -m "First commit" git remote add origin https://rebasely.com//app.git git push -u origin main ``` Your repository's page shows these commands with its own name filled in. If a push is refused, [Push errors](https://rebasely.com/docs/errors) says why. ## What next 1. [Run CI with Actions](https://rebasely.com/docs/actions): Add a workflow under .rebasely/workflows and push: jobs run on Cloudflare Sandboxes. 2. [Edit a live branch](https://rebasely.com/docs/live): rebasely mount / my-idea --create, then save in any editor. 3. [Add an agent](https://rebasely.com/docs/agents): Its own identity, token and limits, working in sandboxes over MCP. 4. [Describe your system](https://rebasely.com/docs/dot-rebasely): A knowledge base and an architecture map that people and agents read first. > **Tip:** Stuck, or something did not work as this page says? [Sign in](https://rebasely.com/signin?return_to=%2Ffeedback) and send us feedback. --- Source: https://rebasely.com/docs/start # Frequently asked questions Short answers, with links to the pages that say more. ## What is Rebasely? Git hosting for people and agents working together: repositories, pull requests, Actions, and features for agents (live branches, sandboxes, agent identities, an MCP server). It runs entirely on Cloudflare: every repository is its own Durable Object. [How it works](https://rebasely.com/docs/how-it-works). ## What does it cost? Nothing today. Rebasely is free within the [published limits](https://rebasely.com/docs/limits). Paid plans with higher limits will come later, and nothing will be charged without you choosing a plan. ## Is it in beta? Rebasely is open to everyone, with a daily number of new signups. Live branches, sandboxes and agents are marked beta: they work, and their limits and details may change. Git hosting, pull requests and Actions are not marked beta. ## Does it work with my git client? Yes. Rebasely speaks git's smart HTTP protocol, protocol v2 included, over HTTPS. Clone, fetch and push work with any git client; partial clones (`--filter=blob:none`) are supported. ## Can I use GitHub Actions workflows? The syntax is close but not the same. Rebasely Actions runs only its built-in actions (`duragit/checkout@v1` and others), not third-party ones, and never allows expressions inside `run:`. [Workflow syntax](https://rebasely.com/docs/workflow-syntax) lists the differences. ## Does Rebasely support Git LFS? Not yet. [What to do with large files](https://rebasely.com/docs/lfs). ## Do I need a passkey? No. Passkeys are optional. Rebasely asks you to confirm it's you before sensitive actions, and you can do that with Google or a passkey. [Sign-in and passkeys](https://rebasely.com/docs/sign-in). ## How do agents get access? Through their own identity and token, never yours. An owner creates the agent, or the agent asks and an owner approves. [Agents and approvals](https://rebasely.com/docs/agents). ## Can I read the docs from a tool or an agent? Yes: [/llms.txt](https://rebasely.com/llms.txt) lists every page, [/llms-full.txt](https://rebasely.com/llms-full.txt) has them all, and every page is Markdown at its address plus `.md`, such as [/docs/start.md](https://rebasely.com/docs/start.md). ## Rebasely used to be called duragit. What changed? Only the name. Old remotes on duragit.com keep working, `duragit` is an alias of the `rebasely` command, and a `.duragit` folder is still read when there is no `.rebasely` one. ## How do I report a security problem? Email security@rebasely.com. [The security page](https://rebasely.com/security) says what happens next. --- Source: https://rebasely.com/docs/faq # Pull requests Propose the changes on a branch or a sandbox, review them line by line, run the checks, and merge them on the server when the base branch's rules are met. ## Opening a pull request A pull request proposes the commits of one branch (the head) for another branch of the same repository (the base, usually the default branch). The head can also be one of your [sandboxes](https://rebasely.com/docs/sandboxes). Writers of the repository open pull requests; everyone who can read the code can read them. - On the web: push a branch, then use **Compare & pull request** on the repository's page or its Pull requests tab, or **New pull request** on the Branches page. The new pull request page shows the commits and the changes before you open it, and fills in the title and description from the commits. - From a terminal: `rebasely pr create --title "Fix the login redirect"` on the branch you pushed. - Agents: the `pr.create` tool, or `POST /api/v1/repos///pulls`. Open it as a draft when it is not ready: a draft cannot be merged until its author (or a writer) marks it ready for review. A branch can have one open pull request per base. Every push to the head shows up in the conversation, and the pull request always shows the head's latest commit. The server keeps the head's commits in `refs/pull//head`, so they stay reachable even when the branch is deleted, and the result of merging the head into the base in `refs/pull//merge`. Neither shows up in branch lists or clones; `git fetch origin refs/pull/12/head` or `rebasely pr checkout 12` gets them. ## Reviewing The Conversation tab has the description, comments, reviews and what happened (pushes, title changes, review requests). Commits lists the commits, and Files changed shows the diff of the head against the point where it left the base. - To comment on a line, select its line number in Files changed. **Comment now** posts the comment at once; **Add to review** keeps it pending, visible only to you, until you submit your review. - Submit a review at the bottom of Files changed: **Comment**, **Approve** or **Request changes**, with a summary. Nobody can approve or request changes on their own pull request. - Reply to a thread under its comments, and resolve it once it is addressed: the pull request's author, writers and whoever started the thread can resolve it. - A thread whose line changed in a later push is marked **Outdated**; it stays in the conversation with the line it was about. - The author and writers ask people for a review in the Reviewers box; they get an email. An approval counts for the commit it was given on: a new push needs a new approval. - Comments, descriptions and reviews are Markdown. Raw HTML is shown as text and images from other sites become links. ### Visual When a pull request changes `.rebasely/architecture` (system.yaml, a view or a dataflow) or `.rebasely/knowledge`, Files changed has a **Code** and **Visual** switch. Code is the line diff. Visual draws what the pull request does to the architecture, with a picker for the diagram: - **System** shows the system as the pull request leaves it: components and connections it adds are marked *added*, ones it changes (kind, description, owned paths, binding) *changed*, and ones it removes stay in place, dashed and struck through, marked *removed*. Select a component for what changed in it. - Each **view** is diffed on its own: the view at the merge base against the view at the head. The picker marks the views the pull request adds, changes or removes. - Each **dataflow** ([flows/\*.yaml](https://rebasely.com/docs/dot-rebasely#flows)) is drawn as numbered steps between its participants: steps the pull request adds are marked *added*, removed ones are dashed and struck through, a step that goes between other participants is *rerouted* (its old route dashed under it), and one with a new label is *relabelled*; a step that moved in the order says where it was. ![Files changed in Visual view: the System diagram marks the billing Worker as added, the actions Worker as changed and the legacy-db database as removed, with a picker for views and dataflows.](https://rebasely.com/static/docs/pr-visual-light.webp?v=0e3244cb6de2) *The Visual view of a pull request that adds a billing Worker and removes a database.* Below each diagram every change is listed, and then the notes and decisions the pull request adds, changes or supersedes in `.rebasely/knowledge`, and a note that moved, or a knowledge base that moved to another folder, as moved. The view and the diagram are in the address (`?view=visual&diagram=flows/upload`), so a link opens the same picture. See [the .rebasely folder](https://rebasely.com/docs/dot-rebasely). ## Merging The merge box at the bottom of the conversation says what stands between the pull request and a merge: its checks, its approvals, conflicts with the base. When nothing does, writers (and the base branch's allowed roles) merge it on the server with one of four methods: | Method | What lands on the base | | --- | --- | | Create a merge commit | A merge commit whose parents are the base and the head (the default). The message names the pull request. | | Squash and merge | One new commit with all the changes, titled with the pull request's title and number. | | Rebase and merge | Each commit of the head replayed onto the base, keeping its author. Only for a straight history of at most 100 commits. | | Fast-forward | The base moves to the head; no new commit. Only when the base has nothing the head does not. | Merges, squashes and rebases write commits, which needs an account at least 7 days old or a verified one (an agent's owner's). Tick **Delete the branch after merging** to remove the head branch in the same step; a protected or live branch, or the default branch, is kept, and a sandbox is ended. When the branches conflict, nothing is written and the merge box lists the files. Merge the base into your branch with git, resolve the conflicts and push: `git merge origin/main`. Histories Rebasely cannot merge on the server (several merge bases, unrelated histories, or changes to `.gitmodules`, `.gitattributes`, symlinks or submodules) say so; merge those with git and push. Pushing the head's commits to the base yourself also counts: the pull request is marked merged by that push. ## Protection, approvals and checks Owners set rules for a branch in the repository's settings, under Branch protection. A merge has to meet the rules of its base: - **Required approvals** (0 to 6): approvals of the latest commit by people with write access other than the author and anyone who pushed to the branch. An agent's approval never counts, and neither does the approval of an agent's owner on the agent's own pull request. A request for changes by a writer blocks the merge until that reviewer approves or an owner dismisses the review. - **Required checks**: commit statuses that must have succeeded on the pull request's head commit, such as `actions/duragit/ci/test`. - **Checks against the current base** (strict): a required check counts only when it ran against the base as it is now; after the base moves, it has to run again. - A branch that requires approvals takes changes only through pull requests: pushes that update it are refused for everyone (`changes need a pull request`), as are force-pushes and deletes. Such a branch cannot be live. > **Note:** The server checks every rule again when the merge is written, whatever the merge box showed. ## Checks from Rebasely Actions Workflows run for pull requests when they declare `on: pull_request`. They run on the result of the merge (`refs/pull//merge`), read their workflow files from it, and report their status on the head commit, which is what the merge box and required checks look at. ``` on: push: branches: [main] pull_request: branches: [main] # the base branch paths: ["src/**"] # files that differ from the base types: [opened, synchronize, reopened] # the default; closed is refused rerun-on-base-change: true # off by default ``` - `opened`, `reopened` and `synchronize` (a push to the head) run the workflow. A pull request that is closed or merged starts nothing; `types: [closed]` is refused. - When the base moves, the head's latest results are marked stale. With `rerun-on-base-change: true` the workflow runs again on the new merge, at most once every 10 minutes per pull request. - A pull request whose author and pushers are all established writers of the organization (people, not agents) runs with the repository's and the organization's secrets; anything else runs without secrets and waits for a different writer to approve the run, at that head. Pull request runs never get deployment environments, never push, and write caches only to their own pull request's scope. - A merge conflict starts nothing and reports `duragit/` as an error saying so, on the head. - Steps see `DURAGIT_PR_NUMBER`, `DURAGIT_HEAD_REF`, `DURAGIT_HEAD_SHA`, `DURAGIT_BASE_REF` and `DURAGIT_BASE_SHA`, and expressions `duragit.pull_request`. - Limit `push` to the base branch, as above: a workflow that runs for both a push to the head and its pull request writes the same check on the head commit, and the later result wins. ## Agents Agents open pull requests, comment, review and merge within their token's repositories, scopes (`repo:write`) and ref patterns, like any writer, with one difference: their approvals are recorded but never count toward required approvals. Over MCP (`https://rebasely.com/mcp`, see [rebasely mcp](https://rebasely.com/docs/mcp)): | Tool | What it does | | --- | --- | | `pr.list` | The repository's pull requests: open, closed, merged or all; a search of titles | | `pr.create` | Open a pull request from a branch or a sandbox | | `pr.get` | A pull request with its merge box, reviews and comments (inline threads with their file and line) | | `pr.diff` | The changes as a unified diff | | `pr.architecture` | What it changes in the architecture (components, connections and views added, removed or changed, each view on its own, and the steps of each dataflow) and in the knowledge base | | `pr.comment` | A comment, on a line with `path`, `line` and `side`, or a reply with `in_reply_to` | | `pr.review` | A review: comment or request changes, with inline comments | | `pr.merge` | Merge with a method, when the base's rules are met | ## The CLI ``` rebasely pr list [--state open|closed|merged|all] [--mine] rebasely pr create --title "..." [--body "..."] [--base main] [--draft] [--reviewer ada@example.com] rebasely pr view 12 [--diff] rebasely pr checkout 12 rebasely pr comment 12 --body "..." [--path src/app.ts --line 42] rebasely pr review 12 --approve | --request-changes | --comment [--body "..."] [--expect ] rebasely pr merge 12 [--method merge|squash|rebase|ff] [--delete-branch] [--expect ] rebasely pr close 12 · rebasely pr reopen 12 · rebasely pr edit 12 --ready ``` Run these in a clone whose remote is `https:////`. The CLI uses `REBASELY_TOKEN` (only for rebasely.com, staging, `$REBASELY_HOST` or a local server), else the remote URL's password, else the token `rebasely auth login` stored for git; it never prints it. `--expect ` binds a review or a merge to the head you read: if someone pushed since, the server refuses. `rebasely` alone opens the terminal UI, whose first panel lists the pull requests. ## The API Under `/api/v1/repos//`, with an access token in `Authorization: Bearer`: | Request | What it does | | --- | --- | | `GET /pulls`, `POST /pulls` | List (`?state=`, `?q=`, `?author=me`); open one (`{title, head, base?, body?, draft?, reviewers?}`) | | `GET /pulls/`, `PATCH /pulls/` | One pull request with its merge box; edit its title, description or draft state, or close and reopen it | | `GET /pulls//commits`, `/files`, `/diff` | Its commits, its changed files, its unified diff | | `GET`, `POST /pulls//comments` | Comments; a new one (general, on a line, or a reply). `PATCH` and `DELETE /comments/` edit and delete yours; `POST /comments//resolve` | | `GET`, `POST /pulls//reviews` | Reviews; submit one (`{event, body?, commit_id?, comments?}`) | | `POST /pulls//reviewers` | Ask people for a review, or stop asking (`{add?, remove?}`) | | `POST /pulls//merge` | Merge (`{method?, expect_head?, delete_branch?, message?}`) | A private repository the token cannot reach, a repository that does not exist and a pull request number that does not exist all get the same `404`. ## Limits | Limit | Value | | --- | --- | | Open pull requests | 1,000 per repository (100,000 in all) | | Opening | 30 pull requests an hour per person or agent in a repository | | Comments and reviews | 300 an hour per person or agent in a repository; 2,500 comments and 500 reviews per pull request; 100 comments in one review; 100 replies in a thread | | Text | titles up to 256 characters, descriptions up to 32,000, comments up to 16,000 | | Requested reviewers | 15 per pull request | | Pages | the newest 250 commits; the first 60 changed files are diffed | | Rebase merges | at most 100 commits, each with one parent | Emails go to people asked for a review, and to a pull request's author and reviewers when it is reviewed or merged; never to whoever did it. They carry the pull request's number and title, nothing anyone else wrote. --- Source: https://rebasely.com/docs/pull-requests # Live branches and rebasely mount Edit one branch together with other people and with agents. Every save reaches everyone in a fraction of a second, Rebasely commits checkpoints as you go, and git keeps working the whole time. > **Beta:** Live branches, sandboxes and agents are in beta. They are free within the [limits below](#limits) while the beta lasts; nothing asks for payment. *Diagram: People save files in a folder that rebasely mount syncs, and agents send edits over MCP. Each save goes to the live branch, which orders the edits and sends them to everyone else connected. Rebasely writes the live state as a checkpoint commit after 10 seconds without edits, after 200 edits, or at least every 2 minutes while edits keep coming. git clones and fetches see the checkpoints.* *People save in their own editors and agents write over MCP; Rebasely orders the edits, sends them to everyone and writes checkpoints.* ## Live branches A live branch is an ordinary branch that several people and agents edit at once. People edit through [rebasely mount](#mount), which syncs a real directory you open in any editor, and agents through the API or the [MCP tools](https://rebasely.com/docs/mcp). The unit is a saved range of lines, not keystrokes. ### Turning live on A writer turns live on from the repository's Live page, with `rebasely mount / --create`, or through the API (`POST /api/v1/repos///live` with `{"ref": ""}`). Turning it off writes a final checkpoint and disconnects everyone. The default branch can be live only after an owner allows it in the repository's settings, under Live and sandboxes. Branches protected with required checks cannot be live. ### Checkpoints are real commits Rebasely commits the live state of the branch as a checkpoint after 10 seconds without edits, after 200 edits, and at least every 2 minutes while edits keep coming. A checkpoint is a normal commit on the branch, authored by whoever made most of its edits, with the others as co-authors. Clones and fetches see checkpoints only, so they always get a consistent tree. Pushes made by checkpoints do not start workflows unless a workflow asks for them with `on: push: {checkpoints: true}`, and then at most once every 5 minutes. ### Pushing to a live branch You can still push with git. Rebasely first writes a checkpoint of any pending edits, then accepts your push if it builds on that checkpoint, and sends your changes to everyone connected. If live edits landed after your last fetch, git says `fetch first` (or `live branch moved: fetch first`): pull, then push again. Force-pushing or deleting a live branch is refused until live is turned off. ### When two edits meet Each edit names the version of the file it was made against. An edit made against an older version is moved past the newer changes when they touch other lines. When two edits touch the same line, the later one is refused with the current lines, and the sender reads again and retries. `rebasely mount` does this for you: it merges cleanly when it can, and otherwise keeps your version next to the file as a conflict copy. Changes to other kinds of files (images, archives) are last writer wins. Paths under `.git`, `.gitmodules`, `.gitattributes`, symlinks and paths matching the repository's ignored patterns are never edited live. ### Watching Members of the organization see each live branch on the repository's Live page: who is connected, which files are changing, the recent changes and the latest checkpoint. On a public repository, anyone signed in can watch, read-only. People who are not signed in see checkpoints through git and the code page, but not live edits. ## rebasely mount Mount a live branch to edit it in any editor. The sync daemon watches the directory, sends each save as a change and writes other people's changes into your files. ### 1. Install the CLI and sign in See [Getting started](https://rebasely.com/docs/start#cli). `rebasely auth login` asks for `live:read` and `live:write` by default. ### 2. Mount the branch From any directory, name the repository and the branch. Mount an existing live branch, or create one from the default branch and turn live on: ```sh rebasely mount team/app feature/login ~/code/app-feature-login rebasely mount team/app my-idea --create ``` Without a path the mount is linked at `./-`, here `./app-my-idea`. Inside a clone of the repository you can leave out `team/app`; `--repo team/app` works too. The Live page of each branch shows its command, ready to copy. ### 3. Edit and save Open the folder in your editor. Every save is sent; other people's saves appear in your files. `git diff origin/` shows what is not in a checkpoint yet. ### 4. Stop `Ctrl-C` stops a foreground mount and keeps it; `rebasely unmount ` stops syncing and removes it. ```sh rebasely mount team/app feature/login ~/code/app # sync in the foreground; Ctrl-C stops it, the mount stays rebasely mount team/app feature/login --daemon # run the daemon in the background rebasely mount team/app my-idea --create # create the branch from the default branch and turn live on rebasely mount team/app feature/login --no-link # keep the mount in ~/.rebasely only, with no link rebasely mounts # every mount and its state rebasely unmount feature/login # stop syncing and remove the mount rebasely mount gc # remove stale mounts that have nothing unsent ``` - Every mount lives under `~/.rebasely` (or `$REBASELY_HOME`; an existing `~/.duragit` keeps being used): one shared object store per repository and one git worktree per branch, so a second branch of the same repository mounts without a fresh clone. The path you give (or `./-`, next to the clone when you run it inside one) is a symlink to the mount. - Run outside a clone without a repository, `rebasely mount` prints the command to run instead, with the repository filled in when the path or the directory names one it can find. - `--adopt` takes an existing clone at that path: its uncommitted changes are sent as edits, and the clone is moved aside, never deleted. - Offline, saves wait in a queue and are sent when the connection comes back. When your change and someone else's touch the same lines, the file gets their version and yours is kept as `.duragit-conflict-`, with a notice in the terminal. A local edit is never dropped silently. - More than 200 files changed within 2 seconds (a checkout, a formatter) pause sending and ask first; `--burst send` or `--burst hold` answers in advance. - Ignored: `.git`, whatever `.gitignore` excludes, the repository's ignored patterns and editor temporary files. - The daemon keeps `origin/` at the latest checkpoint. It never moves your local branch or the index. - `rebasely unmount` keeps a mount with unsent edits until they are delivered; `--discard` drops them. The credential is `REBASELY_TOKEN`, or the token `rebasely auth login` stored for git. ## Limits Live branches, sandboxes and agents are free within these limits during the beta. An edit past a limit is refused with a reason and, where waiting helps, a time to retry. | Limit | Value | | --- | --- | | Edits per connection | 20 a second, bursts of up to 100 | | Edits per branch | 50 a second from everyone together | | Connections per branch | 100, of which 20 may write | | Open live sessions | 10 per person or agent | | One edit | at most 1,000 lines; text files up to 1 MiB, other files up to 10 MiB | | Live branches | 20 per repository, 100 per organization (20 until an owner is verified); live ends after 7 days without edits | | Edits waiting for a checkpoint | 50,000; edits pause until the next checkpoint lands | | Checkpoints | at most one per 10 seconds per branch, 360 an hour and 4,000 a day per repository | | Sandboxes | 20 per person or agent per repository, 200 per repository, 1,000 per organization (200 until an owner is verified) | | Agents | 20 active per organization (5 until an owner is verified, 100 on Team); a person creates at most 10 a day | | Live edits a month | 10,000,000 per organization (2,000,000 until an owner is verified, 20,000,000 on Pro); a checkpoint counts as 40 | Organizations without a verified owner or a paid plan also share a monthly amount of live edits, and a number of live edits a second, with each other. When the month's amount is used up, their live edits are refused until the month ends; at the rate, for a few seconds. Reading, git and checkpoints keep working. Your organization's numbers for this month are on its Trust and limits page. [All of Rebasely's limits](https://rebasely.com/docs/limits) are on one page. ## Sandboxes A sandbox is a hidden branch for one task, `refs/sandbox//`, created in milliseconds and merged back with one command. A sandbox can be live too. [Sandboxes](https://rebasely.com/docs/sandboxes) has the whole flow. ## Agents An agent is an automated tool with its own identity, `dga_` tokens and limits in an organization, and it can ask an owner to [approve](https://rebasely.com/docs/agents#approvals) what only an owner may do. See [Agents and approvals](https://rebasely.com/docs/agents). Approvals are on that page too. ## MCP Agents edit live branches with the `live.*` tools: run `rebasely mcp`, or point an MCP client at `https://rebasely.com/mcp` with `Authorization: Bearer dga_...`. [The MCP server](https://rebasely.com/docs/mcp) lists every tool. --- Source: https://rebasely.com/docs/live # Sandboxes A sandbox is a hidden branch for one task. Create it from any branch or commit in milliseconds, push to it, run its checks, and merge it back with one command. Agents get one per task; people use them for experiments that should not clutter the branch list. > **Beta:** Sandboxes are in beta, free within the [published limits](https://rebasely.com/docs/limits#live). *Diagram: 1. A sandbox is created from a commit of main in milliseconds, as the hidden ref refs/sandbox/a-fixer/fix-login. 2. Its owner pushes commits to it; it never shows up in branch lists or clones. 3. Workflows that declare on: sandbox run its checks. 4. When they pass, the sandbox merges back into main as a fast-forward, a merge commit or one squashed commit, and ends.* *A sandbox leaves main as a hidden ref, gets its own commits and checks, and merges back.* ## How a sandbox works - Its ref is `refs/sandbox//`. The owner is `a-` for an agent and `u-` for a person; the name is yours to pick (lowercase letters, digits, `.`, `_` and `-`, up to 64), or a generated one. - It does not show up in branch lists, ref advertisements or clones. Fetch it by name when you need it. - Only its owner and the repository's owners push to it. A push never creates one: create it with the CLI, the API or the `sandbox.create` tool. - It expires after 24 hours without a push. People can ask for up to 30 days, agents up to 7. An ended sandbox is kept for 7 days for its history. ## From creation to merge ### 1. Create it From `main`, with a git worktree for it next to your clone: ```sh rebasely sandbox create --from main --name fix-login --worktree ../fix-login ``` Without `--worktree`, the CLI prints the fetch, worktree and push commands instead. ### 2. Push to it ```sh cd ../fix-login git commit -am "Fix the login redirect" git push origin HEAD:refs/sandbox//fix-login ``` ### 3. Run its checks Workflows run on a sandbox only if they declare `on: sandbox`, and such runs never get secrets. `--wait` follows them and exits 1 if one fails. ```sh rebasely sandbox checks fix-login --wait ``` ### 4. Merge it ```sh rebasely sandbox merge fix-login --into main --mode squash ``` `--mode` is `ff` (the default), `merge` or `squash`. A merge or a squash writes a commit, which needs an account at least 7 days old or a verified one. A conflicting merge writes nothing and lists the files and lines. `--expect ` refuses the merge if the sandbox moved since you read it. Or open a [pull request](https://rebasely.com/docs/pull-requests) from the sandbox when people should review it first. `rebasely sandbox list` and `rebasely sandbox delete` do what they say. ## The API and MCP CLI: ```sh rebasely sandbox create --from main --name fix-login rebasely sandbox merge fix-login --into main ``` API: ```sh curl -fsS -X POST -H "Authorization: Bearer $REBASELY_TOKEN" -H "content-type: application/json" \ -d '{"from":"main","name":"fix-login"}' https://rebasely.com/api/v1/repos///sandboxes ``` MCP: ```json {"name": "sandbox.create", "arguments": {"repo": "/", "from": "main", "name": "fix-login"}} ``` | Request | What it does | | --- | --- | | `GET /sandboxes` | The repository's sandboxes (`?mine=1`, `?ended=1`) | | `POST /sandboxes` | Create one: `{from?, name?, ttl_s?, live?}` | | `GET`, `DELETE /sandboxes//` | Read or delete one | | `POST /sandboxes///merge` | Merge: `{into?, mode?, expect?, message?, delete?}` | | `POST /sandboxes///checks` | Run its `on: sandbox` workflows | Paths are under `/api/v1/repos//`. A person's token needs `repo:write`, an agent's `sandbox:write`. A sandbox created with `{"live": true}` works like any [live branch](https://rebasely.com/docs/live) until it is merged or deleted. ## Limits and settings At most 20 active sandboxes per person or agent in a repository, 200 per repository and 1,000 per organization. An owner can turn sandboxes off for a repository in its settings, under Live and sandboxes. Creating one then fails with `sandboxes_disabled`; existing sandboxes can still be pushed, merged and deleted. > **Tip:** Coding agents work best with one sandbox and one git worktree per task. `rebasely agent init` adds the [Rebasely agent skill](https://rebasely.com/docs/skills/rebasely/SKILL.md), which tells them to. --- Source: https://rebasely.com/docs/sandboxes # Agents and approvals An agent is an automated tool with its own identity in an organization: its own tokens, bound to the repositories and branches you choose, its own limits, and an off switch that touches nothing else. What only an owner may do, an agent asks an owner to approve. > **Beta:** Agents are in beta, free within the [published limits](https://rebasely.com/docs/limits#live). ## An identity of its own An agent shows up as `/` in pushes, live edits, checkpoints, pull requests and the audit log. Owners of the organization create agents under Settings, Agents, after confirming with Google or a passkey. An agent never signs in and cannot administer anything. - Tokens start with `dga_`. Each works only on the repositories you list for it, and can be limited per repository to ref patterns such as `refs/heads/agent/*` (`*` matches within one part of a ref, `**` across parts). Without patterns it may push wherever its role allows. Agent tokens last 30 days by default and at most 90. - Scopes: `repo:read`, `repo:write`, `repo:create`, `actions:read`, `actions:write`, `statuses:write`, `live:read`, `live:write` and `sandbox:write`. An agent works in its own sandboxes whatever its ref patterns say. - Each agent has its own limits (pushes an hour, API requests a minute, live edits a second and a day, open live sessions, sandboxes, Actions minutes and egress), which an owner can raise up to the plan's ceiling. The agent cannot change them. - Disabling an agent stops its writes at once, closes its live connections, revokes every token and cancels its running jobs. Revoking one token leaves its other tokens working. - An agent's approval of a pull request is recorded but never counts toward required approvals, and an agent counts as an established account only while its owner is. Give an agent its token in `REBASELY_TOKEN`, never your own. At most 20 active agents per organization (100 on Team), and a person creates at most 10 a day. ## Asking an owner to approve A token can ask for what only an owner may do: a new agent, or making a repository public. The request gets a short code; an owner opens [https://rebasely.com/approve](https://rebasely.com/approve), enters it, sees exactly what is asked, and approves after confirming with Google or a passkey. *Diagram: 1. An agent asks Rebasely for something only an owner may do, such as a new agent or making a repository public. 2. Rebasely answers with a short code that expires after 10 minutes. 3. The agent shows the code and the approval page to its person. 4. An owner of the organization opens /approve, enters the code, sees exactly what is asked, and approves after confirming with Google or a passkey. 5. The agent polls every 5 seconds. 6. Once approved, the change is made, and a new agent's token goes to the terminal that asked, once.* *The agent asks, an owner approves on /approve, and the agent's poll gets the answer.* - Requests expire after 10 minutes, are used once, and only the token that asked can follow them. - Making a repository public: the owner who approves needs an established account (7 days old, or verified), and a repository moderation keeps private stays private. Making one private works at once with an owner's token that has `repo:write`. - A new agent: the owner who approves becomes its owner. Its token goes to the terminal that asked, once, never to the approval page. - Every request, approval, denial and token handed out is in the organization's audit log. CLI: ```sh rebasely agent create --org --name fixer --scopes repo:read,repo:write --repos app,web:refs/heads/agent/* rebasely agent token /fixer # print it for REBASELY_TOKEN rebasely repo visibility / public ``` API: ```sh curl -fsS -X POST -H "Authorization: Bearer $REBASELY_TOKEN" -H "content-type: application/json" \ -d '{"kind":"repo_visibility","org":"","repo":"app","visibility":"public"}' https://rebasely.com/api/v1/approvals # then every 5 seconds, until approved, denied or expired: curl -fsS -X POST -H "Authorization: Bearer $REBASELY_TOKEN" https://rebasely.com/api/v1/approvals//poll ``` MCP: ``` agent.request ask for a new agent repo.visibility ask to make a repository public approval.status follow the request ``` `rebasely agent create` also takes `--role`, `--description`, `--expires` and `--caps pushes_per_hour=60`. The CLI keeps the token in the system keychain. ## Creating repositories A token with `repo:create` creates repositories, always private. `rebasely auth login` asks for it by default; an agent's token has it only when an owner grants it, and each repository it creates is added to the token. The usual rules apply: writers and owners, the reserved names, 100 repositories a day per person (an agent's count against its owner), plus 20 an hour per token and 60 an hour per organization from tokens. ```sh rebasely repo create / --description "What it is" --default-branch main --readme ``` ## The agent skill `rebasely agent init` adds the [Rebasely agent skill](https://rebasely.com/docs/skills/rebasely/SKILL.md) to a repository (`.claude/skills/rebasely/`). It tells coding agents to work in one [sandbox](https://rebasely.com/docs/sandboxes) and one git worktree per task, to read the [knowledge base and architecture](https://rebasely.com/docs/dot-rebasely) first, and to keep them current. --- Source: https://rebasely.com/docs/agents # SSH access is turned off Rebasely no longer offers git over SSH. Clone, fetch and push over HTTPS instead: it has the same permissions, limits and answers. ## Use HTTPS The Rebasely CLI signs git in with an access token you approve in the browser: ``` rebasely auth login ``` Or create an [access token](https://rebasely.com/settings/tokens) and paste it when git asks for a password. [Getting started](https://rebasely.com/docs/start) has the full steps. ## Switch an existing clone Point a repository that used an SSH remote at its HTTPS address: ``` git remote set-url origin https://rebasely.com//.git ``` Your SSH keys stay listed in your [SSH key settings](https://rebasely.com/settings/ssh), where you can remove them. If you set up SSH with `rebasely ssh setup` before, you can delete the Rebasely block at the top of `~/.ssh/config`. A connection refused with `ssh_off` means the same thing: SSH is off, use HTTPS. --- Source: https://rebasely.com/docs/ssh # How Rebasely works Rebasely runs entirely on Cloudflare. Every repository is its own Durable Object, a single writer that holds the repository's refs, so a push lands whole or not at all, close to where you are. *Diagram: 1. git sends the push to the Rebasely Worker at the edge. 2. The Worker checks the token and the role and reads the refs from the repository's Durable Object. 3. It hands the pack to a push job, a Durable Object of its own. 4. The push job checks every object and stores the pack in R2. 5. It commits the push with the repository's Durable Object, which moves the refs in one step. 6. The repository sends one event per updated ref, which starts Actions and notifications.* *A push: the Worker checks it, a push job stores the pack, and the repository's own Durable Object moves the refs.* ## What happens on a push ### 1. The Worker takes the request git talks to the Rebasely Worker at the Cloudflare location nearest to you, over HTTPS. The Worker checks your token and your role in the organization, and asks the repository's Durable Object for its refs. ### 2. A push job checks the pack Each push gets a Durable Object of its own. It reads the pack, checks every object the way `git fsck --strict` does, scans for leaked Rebasely tokens and private keys, and stores the pack in R2. Large or unusual pushes are verified with real git in a sandbox first. ### 3. The repository commits it The repository's Durable Object checks the ref updates against protection rules and live branches and moves every ref in one step. Then it reports the result to git and sends one event per updated ref, which starts [Actions](https://rebasely.com/docs/actions) and notifications. ## The pieces | Piece | What it does | | --- | --- | | Worker | Serves the web pages, the API, MCP and git over HTTPS; checks every request's credential and permissions. | | Repository (Durable Object) | One per repository: its refs, live branches, sandboxes, pull request state and outbox of events. | | Push job (Durable Object) | One per push: checks and stores the pack, then commits it with the repository. | | R2 | Packs and objects, and Actions logs, artifacts and caches. | | D1 | Accounts, organizations, tokens and other data that is not a repository's. | | Cloudflare Sandboxes | Actions jobs, and the real git that verifies unusual pushes. | ## Reads Clones and fetches are served from the repository's packs in R2, through the Worker. A private repository the reader cannot see answers exactly like one that does not exist, for git, the API, MCP and the web pages. > **Note:** Rebasely's own architecture is described in its [.rebasely folder](https://rebasely.com/docs/dot-rebasely) the same way you can describe yours. --- Source: https://rebasely.com/docs/how-it-works # The .rebasely folder One folder at the root of a repository holds what people and agents need besides the code: a knowledge base, a map of the system and the workflows that build it. Rebasely shows the first two on the repository's Concepts tab and serves them to agents over MCP. ## Layout Everything is plain files, reviewed and versioned with the code they describe. All three parts are optional; add the one you need first. ``` .rebasely/ knowledge/ index.md where to start: links to every note concepts/storage.md how a part of the system works decisions/0001-r2-for-blobs.md numbered, append-only decisions guides/local-dev.md how to do something architecture/ system.yaml components, the code they own, what they talk to views/write-path.yaml a subset of the components flows/upload.yaml a dataflow: the ordered steps of one request workflows/ ci.yml Rebasely Actions ``` ## A .duragit folder Rebasely used to be called duragit, and the folder was `.duragit/`. Repositories that still have one keep working. For each of `architecture` and `workflows`, Rebasely uses `.rebasely/` when it exists, and `.duragit/` otherwise. The knowledge base was called `kb/` until October 2026, so Rebasely reads the first of `.rebasely/knowledge`, `.rebasely/kb` and `.duragit/kb` that exists. The folders are never merged: once `.rebasely/knowledge/` exists, nothing in the older ones is read. The same rule holds for the Concepts tab, for agents over MCP, for Actions, and for `rebasely kb check` and `rebasely arch check`. To move a repository over, rename the folders and push: `git mv .duragit .rebasely`, then `git mv .rebasely/kb .rebasely/knowledge`. A pull request that does only that shows the knowledge base as moved, with no note changed. ## Knowledge base Markdown notes in `.rebasely/knowledge/`, in folders you make, up to four levels deep, the way you organize code. A common start: `concepts/` explain how something works, `decisions/` record why it is that way, `guides/` say how to do something. `index.md` is the start of the notes on the Concepts tab, and a folder's own `index.md` or `README.md` shows under its list of files. Each note starts with YAML frontmatter and a `# Title`, and links to other notes by id with `[[id]]`: ```markdown --- id: storage type: concept owner: ada component: api describes: - src/api/storage/** reviewed: 2026-10-01 --- # Storage Uploads stream to R2 as they arrive; see [[0001-r2-for-blobs]] for why, and [[local-dev]] to run it on your machine. ``` - `id` is the file name without `.md`, in kebab-case; `type` is `concept`, `decision` or `guide`; `owner` is who keeps it current; `reviewed` is the date someone last checked it against the code. - A concept says which code it `describes` (path patterns) and may name its `component` in `system.yaml`. The Concepts tab links both. - Decisions are numbered (`NNNN-name.md`) and append-only: once accepted, a decision is not rewritten. A later one replaces it, and the old one gets `status: superseded` and `superseded-by: `. The Concepts tab shows each decision's number and status, and which decision replaced it. ```markdown --- id: 0002-signed-download-links type: decision owner: ada status: accepted --- # 0002 Signed download links Private files are served through links signed for one reader... ``` The Concepts tab shows the notes as they are in the repository: the folder tree beside each folder or note, at an address that mirrors the path (`.rebasely/knowledge/decisions/0002-signed-download-links.md` is `///concepts/decisions/0002-signed-download-links`), with breadcrumbs and View source on every page. It resolves every `[[id]]` to its note (a link to a note that does not exist is marked missing), shows which notes link to each one, and searches titles and text. Markdown renders as in a README: no raw HTML, and relative links go to the repository's files. ## Architecture `.rebasely/architecture/system.yaml` lists the components of the system: what `kind` each is (`worker`, `durable-object`, `r2-bucket`, `d1`, `kv`, `queue`, `container`, `library` or `external`), the code it `owns` (path patterns; every file has at most one owner), its `binding` in the Worker's wrangler config, and what it `talks_to`, with the kind of each connection: ```yaml components: api: kind: worker description: The HTTP API and the upload path. owns: [src/api/**] talks_to: - { to: repo-do, via: rpc } - { to: blobs, via: r2 } repo-do: kind: durable-object description: One per repository; owns its refs. binding: REPO owns: [src/repo/**] blobs: kind: r2-bucket binding: BLOBS ``` A view in `views/.yaml` is a subset worth looking at on its own: ```yaml description: What an upload touches. components: [api, blobs] ``` A dataflow in `flows/.yaml` is one thing the system does, step by step: a `title`, a `description`, and `steps` in order, each going `from` one participant `to` another with a short `label`. A participant is a component of `system.yaml` or one of the flow's `actors`, the people and programs outside the system (a browser, a git client). Quote a label that has a comma in it. ```yaml title: An upload description: A file goes to R2 and the repository records it. actors: [browser] steps: - { from: browser, to: api, label: PUT /files/:name } - { from: api, to: repo-do, label: reserve the name } - { from: api, to: blobs, label: stream the bytes } - { from: api, to: repo-do, label: "commit the file, then answer" } ``` A flow has at most 60 steps and 10 actors, a label at most 80 characters and a title at most 100; a repository has at most 50 flows, each file at most 256 KiB. When a pull request changes a flow, its Files changed page shows the flow under [Visual](https://rebasely.com/docs/pull-requests#visual) as numbered steps between the participants, with the steps it adds, removes, reroutes (the same label between other participants), relabels and moves. When a pull request changes any of these files, its Files changed page can show the change as a picture: the [Visual](https://rebasely.com/docs/pull-requests#visual) view. *Diagram: Files changed has a Code and Visual switch. Visual draws the system as the pull request leaves it: the billing Worker it adds and its connections are marked added, the objects bucket it changes is marked changed, and the legacy-db database it removes stays in place, dashed and struck through, with its connection.* *Visual marks what a pull request adds, changes and removes in the architecture.* The Concepts tab opens with the architecture: it draws the components and their connections, with a switcher for the views, and lists each component with its description, owned paths (linked to the files), binding and connections. Select a component to see what it talks to and what uses it. If paths a component owns are gone from the branch, the page says the map may be out of date. ## Workflows `.rebasely/workflows/*.yml` are Rebasely Actions workflows: push them and their jobs run on Cloudflare Sandboxes. The repository's Actions tab lists the runs and has a starter workflow to copy. ## Keeping it honest Notes and maps go stale when nothing checks them. The [Rebasely CLI](https://rebasely.com/docs/start#git) does, in the repository's working tree: - `rebasely kb check` checks every note's frontmatter, that each `[[id]]` names a note, that a superseded decision names a decision that exists, and that each `component` is in `system.yaml`. It marks a concept stale when code it `describes` changed in commits after the note was last edited, until someone edits the note or moves `reviewed` past those commits. `rebasely kb list` shows each note's state. - `rebasely arch check` checks `system.yaml` against the code: every owned pattern matches files, no file has two owners, each binding exists in the wrangler config with the right kind, and every connection it finds in the code (imports, `env.BINDING` reads, service bindings) is declared in `talks_to`, and the other way round. It checks that every view and flow names only components of `system.yaml` (or, in a flow, its own actors), that every step has a label and goes between two different participants, and that flows stay within the limits above. Both exit 1 when something is wrong, so they fit in a workflow (staleness needs the history, so check out more than the last commit): ```yaml - run: curl -fsSL https://rebasely.com/cli/rebasely.mjs -o /tmp/rebasely.mjs - run: node /tmp/rebasely.mjs kb check - run: node /tmp/rebasely.mjs arch check ``` ## Agents Agents read the same context through the [MCP server](https://rebasely.com/docs/mcp): `kb.list` lists the notes, `kb.read` returns one with its links resolved and the notes that link to it, `kb.search` searches them, and `arch.get` returns the components and connections, of one view or around one component. They answer only what the token may read; a private repository the token cannot reach gets the same answer as one that does not exist. The [Rebasely agent skill](https://rebasely.com/docs/skills/rebasely/SKILL.md) tells coding agents to read the knowledge base and the architecture before they change anything, and to update the notes, add a decision and fix `system.yaml` in the same change when they change behavior. --- Source: https://rebasely.com/docs/dot-rebasely # CLI reference Every `rebasely` command and flag. This page is generated from the CLI's own help, so it matches what `rebasely help` prints. ```sh curl -fsSL https://rebasely.com/install | sh ``` The CLI is one file and needs Node.js 22.18 or later. `duragit` is an alias of `rebasely`. Every command takes `--json` for scripts, CI and agents. Exit codes: 0 when it worked, 1 when a check failed, 2 for a usage error or outside a git repository. ## General | Command | What it does | | --- | --- | | `rebasely` | open the TUI | | `rebasely help` | this help | ## Pull requests | Command | What it does | | --- | --- | | `rebasely pr list` | pull requests: \[`--state open\|closed\|merged\|all`\] \[`--mine`\] | | `rebasely pr view ` | one pull request, what blocks its merge, its reviews and comments: \[`--diff`\] \[`--tab a\|c\|b\|r\|v`\] (summary, code, kb, architecture, conversation) | | `rebasely pr create` | `--title T` \[`--body B`\] \[`--head branch`\] \[`--base branch`\] \[`--draft`\] \[`--reviewer `\]... | | `rebasely pr checkout ` | fetch the PR's head into the local branch pr/`` and switch to it | | `rebasely pr comment ` | `--body B` \[`--path file` `--line n` \[`--side new\|old`\]\] \[`--reply `\] | | `rebasely pr review ` | `--approve` \| `--request-changes` \| `--comment`, with \[`--body B`\] | | `rebasely pr edit ` | \[`--title T`\] \[`--body B`\] \[`--draft` \| `--ready`\] | | `rebasely pr close ` | close; rebasely pr reopen `` reopens | | `rebasely pr merge ` | merge on the server: \[`--method merge\|squash\|rebase\|ff`\] \[`--delete-branch`\] \[`--message M`\] | ## Branches | Command | What it does | | --- | --- | | `rebasely branch list` | branches compared with the base branch | | `rebasely branch show ` | one branch: `--tab a\|c\|b\|r` | ## Knowledge base and architecture | Command | What it does | | --- | --- | | `rebasely kb list` | knowledge base docs and their state | | `rebasely kb check` | KB shapes, links and staleness; exits 1 on problems | | `rebasely arch check` | system.yaml against the code; exits 1 on errors | ## Actions | Command | What it does | | --- | --- | | `rebasely runs list` | Actions runs: \[`--workflow file`\] \[`--branch b`\] \[`--status s`\] \[`--limit n`\] | | `rebasely runs logs ` | a job's log: \[`--job key`\] \[`--attempt n`\] \[`--follow`\] | | `rebasely runs cancel ` | cancel a run | | `rebasely dispatch ` | start a manual run: \[`--ref branch`\] \[`--input name`=value\]... | ## Sandboxes | Command | What it does | | --- | --- | | `rebasely sandbox create` | a sandbox branch: \[`--from ref`\] \[`--name n`\] \[`--ttl seconds`\] \[`--worktree path`\] | | `rebasely sandbox list` | sandboxes of the repo: \[`--mine`\] \[`--ended`\] | | `rebasely sandbox merge ` | merge a sandbox: \[`--into branch`\] \[`--mode ff\|merge\|squash`\] \[`--message M`\] \[`--expect sha`\] \[`--keep`\] | | `rebasely sandbox delete ` | delete a sandbox | | `rebasely sandbox checks ` | run the workflows that declare on: sandbox: \[`--wait`\] | ## Repositories | Command | What it does | | --- | --- | | `rebasely repo create /` | create a private repository (needs repo:create, on by default after auth login): \[`--description D`\] \[`--default-branch B`\] \[`--readme`\] | | `rebasely repo visibility / public\|private` | private at once with an owner's token; public (or a token that may not) asks an owner to approve with a passkey on ``/approve and waits: \[`--no-wait`\] | ## Agents and approvals | Command | What it does | | --- | --- | | `rebasely agent init` | add the Rebasely agent skill to this repo (.claude/skills/rebasely/): \[`--dir path`\] \[`--force`\] \[`--print`\] | | `rebasely agent create` | ask an owner to approve a new agent identity: `--org O` `--name N` `--scopes a`,b `--repos r1`,r2\[:pattern...\] \[`--role writer\|reader`\] \[`--description D`\] \[`--expires days`\] \[`--caps key`=value,...\] \[`--no-wait`\]; its token comes back once, into the system keychain \[`--print-token`\] | | `rebasely agent token /` | print an agent's token from the keychain (`REBASELY_TOKEN`=$(...)) | | `rebasely approval wait ` | follow an approval request (started by an MCP tool, say) to its answer | | `rebasely approval status ` | an approval request's state | ## Sign-in | Command | What it does | | --- | --- | | `rebasely auth login` | sign git in with an access token you approve in the browser: \[`--org `\]... \[`--scopes `\] \[`--expires `\] \[`--yes`\] \[`--allow-plaintext-store`\]; `--all-orgs instead` of `--org`: one token for every organization you belong to, including ones you join later (90 days unless `--expires is` shorter, 365 at most) | | `rebasely auth status` | the stored token's account, organizations, scopes and expiry | | `rebasely auth logout` | revoke the stored token and remove it from git's credential helper | ## Live branches | Command | What it does | | --- | --- | | `rebasely mount / []` | edit a live branch in a real directory, synced as you save; works anywhere, and inside a clone ``/`` may be left out. `` defaults to ./``-``: \[`--host url`\] \[`--create`\] \[`--adopt`\] \[`--burst ask\|send\|hold`\] \[`--daemon`\] \[`--no-link`\] (`--repo org`/repo also names the repository) | | `rebasely unmount stop syncing and remove the mount: [--discard] [--repo org/repo]` | | | `rebasely mounts` | the mounts under the managed home and their state | | `rebasely mount gc` | remove stale mounts that have no unsent edits | ## MCP | Command | What it does | | --- | --- | | `rebasely mcp` | a stdio MCP server for local agents, proxied to ``/mcp with your credential: \[`--host url\|staging\|production`\] | ## Hosts, tokens and the home folder Actions and sandbox commands (runs, dispatch, sandbox) talk to the origin remote's server and repo, or to `--host ` and `--repo `/``. The token comes from `REBASELY_TOKEN` (or DURAGIT\_TOKEN), else from git's credential helper for that host; it is never printed. auth talks to rebasely.com, or to `--env staging` or `--host `; it never prints a token. Git over SSH was retired in 2026-11: use HTTPS. The managed home (mounts) is `$REBASELY_HOME`, else `~/.rebasely`, or `~/.duragit` when that is the one that exists. Every REBASELY\_ variable may also be given by its older DURAGIT\_ name. > **Tip:** Point the CLI at staging or a local server with `--host ` (or `--env staging` for `auth` and `ssh`). The token is only ever sent to Rebasely's own hosts, `$REBASELY_HOST` or a local development host. --- Source: https://rebasely.com/docs/cli # REST API Everything the web pages and the CLI do with repositories, pull requests, sandboxes, live branches and Actions, as JSON under `https://rebasely.com/api/v1`. ## Authentication Send an access token in `Authorization: Bearer `. Personal tokens start with `dgp_`, agent tokens with `dga_`. A token works within its scopes, its organization (or, for a token of all your organizations, wherever you are a member, with your role there) and the repositories it is limited to; [Access tokens](https://rebasely.com/docs/tokens) lists the scopes. curl: ```sh curl -fsS -H "Authorization: Bearer $REBASELY_TOKEN" https://rebasely.com/api/v1/user ``` JavaScript: ```js const res = await fetch("https://rebasely.com/api/v1/repos/acme/app/pulls?state=open", { headers: { authorization: `Bearer ${process.env.REBASELY_TOKEN}` }, }); const { pulls } = await res.json(); ``` ## Errors Errors are JSON with a code and a sentence: `{"error": "forbidden", "message": "...", "reason": "missing_scope"}`. | Status | error | When | | --- | --- | --- | | 401 | `unauthorized` | No token, or one that is malformed, unknown, expired or revoked. | | 403 | `forbidden` | You can read the repository but the token lacks the scope or the role; `reason` says which. | | 403 | `approval_required` | Only an owner may do this: the answer includes the [approval](https://rebasely.com/docs/agents#approvals) to start. | | 404 | `not_found` | The repository, pull request or sandbox does not exist, or the token cannot see it: the two answers are the same. | | 409, 422 | various | A conflict, or a request the server understood but cannot do (a merge that conflicts, a name that is taken). | | 429 | `rate_limited` | Too many requests; wait for `Retry-After` seconds. | ## Rate limits 1,200 requests a minute per token (or per signed-in person), and 600 a minute per agent across all its tokens. Lists page with `?limit=` (1 to 100, 25 by default) and a cursor: `?cursor=` for Actions runs, `?before=` for pull requests. ## You and your token | Request | What it does | Scope | | --- | --- | --- | | `GET /user` | Who the token belongs to: the account, organizations, scopes and expiry | `any` | | `DELETE /tokens/current` | The token revokes itself | `any` | ## Repositories | Request | What it does | Scope | | --- | --- | --- | | `GET /repos/:org/:repo` | The repository: visibility, default branch, description | `repo:read` | | `POST /orgs/:org/repos` | Create a private repository: {name, description?, default\_branch?, init?: {readme: true}} | `repo:create` | | `POST /repos/:org/:repo/visibility` | {visibility}: private at once for an owner; public asks an owner to approve | `repo:write` | ## Pull requests Under `/repos/:org/:repo`. [Pull requests](https://rebasely.com/docs/pull-requests#api) has the bodies. | Request | What it does | Scope | | --- | --- | --- | | `GET /pulls` | List: ?state=open\|closed\|merged\|all, ?q=, ?author=me | `repo:read` | | `POST /pulls` | Open one: {title, head, base?, body?, draft?, reviewers?} | `repo:write` | | `GET, PATCH /pulls/:n` | One pull request with its merge box; edit, close or reopen it | `repo:read, repo:write` | | `GET /pulls/:n/commits, /files, /diff, /architecture` | Its commits, files, unified diff, and what it changes in the architecture | `repo:read` | | `GET, POST /pulls/:n/comments` | Comments; a new one, on a line or as a reply | `repo:read, repo:write` | | `GET, POST /pulls/:n/reviews` | Reviews; submit one: {event: approve\|request\_changes\|comment, body?, comments?} | `repo:read, repo:write` | | `POST /pulls/:n/reviewers` | Ask for reviews: {add?, remove?} | `repo:write` | | `POST /pulls/:n/merge` | Merge: {method?: merge\|squash\|rebase\|ff, expect\_head?, delete\_branch?} | `repo:write` | ## Sandboxes | Request | What it does | Scope | | --- | --- | --- | | `GET, POST /repos/:org/:repo/sandboxes` | List; create one: {from?, name?, ttl\_s?, live?} | `repo:write` or `sandbox:write` | | `GET, DELETE .../sandboxes/:owner/:name` | Read or delete one | `repo:write` or `sandbox:write` | | `POST .../sandboxes/:owner/:name/merge` | Merge: {into?, mode?: ff\|merge\|squash, expect?, message?} | `repo:write` or `sandbox:write` | | `POST .../sandboxes/:owner/:name/checks` | Run its on: sandbox workflows | `repo:write` or `sandbox:write` | ## Live branches | Request | What it does | Scope | | --- | --- | --- | | `GET, POST, DELETE /repos/:org/:repo/live` | Live branches; turn live on ({ref}) or off (?ref=) | `live:read, live:write` | | `GET .../live/files, .../live/tree` | A file with its version; a directory | `live:read` | | `POST .../live/ops?ref=` | Edits: {session, ops}, at most 100 | `live:write` | | `GET .../live/events` | Changes as server-sent events, resumable with Last-Event-ID | `live:read` | | `POST .../live/locks, .../live/presence, .../live/checkpoint` | Soft locks, presence, a checkpoint now | `live:write` | ## Actions | Request | What it does | Scope | | --- | --- | --- | | `GET /repos/:org/:repo/actions/runs` | Runs: ?workflow, ?branch, ?status, ?sha, ?limit, ?cursor | `actions:read` | | `GET .../actions/runs/:id` | One run with its jobs | `actions:read` | | `POST .../actions/runs/:id/cancel` | Cancel a run | `actions:write` | | `POST .../actions/workflows/:file/dispatches` | Start a manual run: {ref, inputs} | `actions:write` | | `GET .../commits/:sha/statuses` | A commit's statuses | `repo:read` | | `POST .../statuses/:sha` | Post a status: {state, context, description?, target\_url?} | `statuses:write` | ## Approvals | Request | What it does | Scope | | --- | --- | --- | | `POST /approvals` | Ask an owner: {kind: repo\_visibility \| agent\_create, ...} | `any token` | | `GET /approvals/:id` | The request's state | `the token that asked` | | `POST /approvals/:id/poll` | Poll every 5 seconds; an approved new agent's token comes back once | `the token that asked` | > **Note:** Managing agents (`/orgs/:org/agents`) works with a signed-in owner's session only, never with a token: no token can create another. --- Source: https://rebasely.com/docs/api # MCP server Agents that speak the Model Context Protocol use Rebasely's tools directly: live branches, sandboxes, checks, pull requests, the knowledge base and the architecture. Each tool has the same permissions as the API request behind it. ## Connect Remote: ``` https://rebasely.com/mcp Authorization: Bearer dga_... ``` Local proxy: ```sh rebasely mcp # a stdio MCP server; --host staging|production| ``` - **Remote:** point the client at `https://rebasely.com/mcp` (Streamable HTTP) with the header `Authorization: Bearer dga_...` (an agent token) or `dgp_...` (a personal token). Tokens are accepted in that header only, never in the URL; a request from another site's page is refused. - **Local:** `rebasely mcp` runs a stdio server that forwards to `/mcp` with the credential the CLI has (`REBASELY_TOKEN`, or the token `rebasely auth login` stored). ```json { "mcpServers": { "rebasely": { "command": "rebasely", "args": ["mcp"] } } } ``` ## Tools | Tool | What it does | Scope | | --- | --- | --- | | `live.read` | A file with line numbers and its version | `live:read` | | `live.tree` | Paths of a directory with their versions | `live:read` | | `live.write` | Line-range edits against a version, or a whole file (at most 100 edits) | `live:write` | | `live.subscribe` | Changes since a point, each with a one-line summary; waits up to 25 seconds for the next | `live:read` | | `live.presence` | Say what you are looking at; see who is connected | `live:read` | | `live.lock`, `live.unlock` | A soft lock on a file, for up to 5 minutes | `live:write` | | `live.checkpoint` | Write a checkpoint now, at most one per 10 seconds | `live:write` | | `sandbox.create`, `sandbox.list`, `sandbox.merge`, `sandbox.delete` | Sandboxes | `sandbox:write or repo:write` | | `checks.run` | Run a sandbox's on: sandbox workflows | `sandbox:write or repo:write` | | `checks.status` | The commit statuses of a commit | `repo:read` | | `pr.list`, `pr.get`, `pr.diff` | Pull requests, one with its merge box, reviews and comments, its diff | `repo:read` | | `pr.architecture` | What a pull request changes in the architecture and the knowledge base | `repo:read` | | `pr.create`, `pr.comment`, `pr.review`, `pr.merge` | Open, comment, review and merge | `repo:write` | | `kb.list`, `kb.read`, `kb.search` | The knowledge base: notes, one note with its links and backlinks, a search | `repo:read` | | `arch.get` | The architecture: all of it, one view's or one component's | `repo:read` | | `repo.create` | Create a private repository | `repo:create` | | `repo.visibility`, `agent.request`, `approval.status` | Ask an owner to approve, and follow the request | no scope | Every tool names its repository as `/`. A private repository the token cannot reach gets the same answer as one that does not exist. ## Limits The same as the API: 1,200 requests a minute per token, 600 a minute per agent across all its tokens, a batch of at most 20 messages and 2 MiB. Protocol versions 2025-06-18, 2025-03-26 and 2024-11-05. > **Tip:** Start an agent with `kb.list` and `arch.get`: the [.rebasely folder](https://rebasely.com/docs/dot-rebasely) tells it how the system fits together before it changes anything. --- Source: https://rebasely.com/docs/mcp # Limits Every limit Rebasely enforces, in one place. A request past a limit is refused with a reason and, where waiting helps, a time to retry; nothing you already stored is touched. > **Note:** Rebasely is free within these limits. Paid plans with higher limits will come later. ## Repositories and pushes | Limit | Value | | --- | --- | | Repository size | a warning at 1 GB; pushes are refused at 5 GB | | One push | 100 MB, counting the pack git builds for it; one object at most 100 MiB, a push at most 1,000,000 objects | | Pushes | 300 an hour and 5,000 a day per repository; 20,000 a day (UTC) per organization | | Branches and tags | 100,000 per repository; 1,000 ref updates in one push | | Raw files | 10 MiB each | | New repositories | 100 a day per person (an agent's count against its owner); 20 an hour per token and 60 an hour per organization from tokens | | New organizations | 10 a day per person | [What git prints](https://rebasely.com/docs/errors#limits) when a push meets one of these. ## API and MCP | Limit | Value | | --- | --- | | Requests | 1,200 a minute per token or signed-in person; 600 a minute per agent across all its tokens | | MCP | a batch of at most 20 messages and 2 MiB | | Access tokens | expire after 1 to 365 days (90 by default); agent tokens after at most 90 (30 by default) | ## Pull requests | Limit | Value | | --- | --- | | Open pull requests | 1,000 per repository (100,000 in all) | | Opening | 30 an hour per person or agent in a repository | | Comments and reviews | 300 an hour per person or agent in a repository; 2,500 comments and 500 reviews per pull request | | Text | titles up to 256 characters, descriptions up to 32,000, comments up to 16,000 | | Rebase merges | at most 100 commits | ## Live branches, sandboxes and agents | Limit | Value | | --- | --- | | Edits per connection | 20 a second, bursts of up to 100 | | Edits per branch | 50 a second from everyone together | | Connections per branch | 100, of which 20 may write | | Open live sessions | 10 per person or agent | | One edit | at most 1,000 lines; text files up to 1 MiB, other files up to 10 MiB | | Live branches | 20 per repository, 100 per organization (20 until an owner is verified); live ends after 7 days without edits | | Edits waiting for a checkpoint | 50,000; edits pause until the next checkpoint lands | | Checkpoints | at most one per 10 seconds per branch, 360 an hour and 4,000 a day per repository | | Sandboxes | 20 per person or agent per repository, 200 per repository, 1,000 per organization (200 until an owner is verified) | | Agents | 20 active per organization (5 until an owner is verified, 100 on Team); a person creates at most 10 a day | | Live edits a month | 10,000,000 per organization (2,000,000 until an owner is verified, 20,000,000 on Pro); a checkpoint counts as 40 | Sandboxes: at most 20 active per person or agent in a repository. ## Actions | Limit | Free | | --- | --- | | Jobs at once | 2 per organization | | Largest instance | standard-1 (0.5 vCPU, 4 GiB memory, 8 GB disk) | | Longest job | 60 minutes | | Compute | 2,000 vCPU-minutes a month | | Egress | 10 GB a month | | Artifacts | 1 GiB per run, kept 30 days | | Logs | 64 MiB per job, kept 30 days | | Workflows | 20 files per repository, 64 KiB each; 256 jobs per run, 100 steps per job | [Instances and images](https://rebasely.com/docs/actions#runners) are on the Actions page. ## Your account | Limit | Value | | --- | --- | | Sessions | end after 14 days without use, and after 30 days in any case | | Confirmation | lasts 2 hours after you confirm it's you with Google or a passkey | | New accounts | until an account is 7 days old (or verified) it cannot make a repository public, write to live branches, approve Actions runs or have the server write merges | | Data exports | 3 a day, one at a time | --- Source: https://rebasely.com/docs/limits # Push errors What git prints when Rebasely refuses a push, and how to get the push through. A refused push changes nothing: no branch or tag moves and nothing is stored. Rebasely's reason appears in parentheses at the end of the ` ! [remote rejected]` line, or after `remote:` and `remote unpack failed: error`. ## The push is larger than 100 MB ``` error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 send-pack: unexpected disconnect while reading sideband packet fatal: the remote end hung up unexpectedly remote: Rebasely: this push is over the 100 MB request limit. See https://rebasely.com/docs/errors#413 fatal: the remote end hung up unexpectedly ``` One push can send at most 100 MB (100,000,000 bytes), counting the pack git builds for it. Most larger requests are refused before Rebasely reads them, so git can print only the HTTP status. When Rebasely had already started on the push, git prints the second message instead. To push a large history, send it in parts, oldest first. For example, push a commit about halfway back, then the rest: ``` git push origin HEAD~500:refs/heads/main git push origin main ``` A single commit that adds more than 100 MB of files cannot be pushed. Keep build output, datasets and media out of the repository; Rebasely does not support Git LFS ([why, and what to do instead](https://rebasely.com/docs/lfs)). Raising `http.postBuffer` does not help: the limit applies to the whole request. ## Server busy: large push could not be processed ``` ! [remote rejected] main -> main (server busy: large push could not be processed, retry later) ``` Pushes with a pack over 32 MiB, with a single file over 8 MiB, or whose files take far more space than the pack (for example many versions of a large file) are processed in a separate sandbox. It was busy or unavailable, so the push was refused. Retry in a few minutes. ## Verification service unavailable ``` ! [remote rejected] main -> main (verification service unavailable, retry) ``` Some pushes are checked with real git before any branch moves: pushes that add submodules, symlinks or `.gitmodules` and `.gitattributes` files, pushes from accounts younger than 7 days, and large pushes. The checker could not run, so the push was refused. Retry in a few minutes. ## An active Rebasely token in the push ``` ! [remote rejected] main -> main (push contains an active Rebasely token in deploy.env; it has been revoked) ``` A file in the push contains one of your access tokens. Rebasely revoked the token at once and emailed its owner, because anyone who can read the repository could have used it. Remove the token from the file and from every commit in the push (`git commit --amend` for the last commit, `git rebase -i` for older ones), create a new token in [your token settings](https://rebasely.com/settings/tokens), keep it out of the repository, and push again. ## Fetch first ``` ! [remote rejected] main -> main (fetch first) ``` The branch moved on the server since you last fetched it, for example because someone else pushed. Run `git pull --rebase` (or fetch and merge), then push again. A tag that already exists gets `already exists` instead. ## Protected branch ``` ! [remote rejected] main -> main (protected branch: force-push not allowed) ! [remote rejected] main (protected branch: deletion not allowed) ! [remote rejected] main -> main (protected branch: push not allowed for role writer) ! [remote rejected] main -> main (protected branch: required check build has not succeeded) ``` The branch has a protection rule. Push a commit that builds on the branch instead of rewriting it, push to another branch, or ask an owner of the repository to change the rule in the repository's settings. ## Deleting the default branch ``` ! [remote rejected] main (deletion of the current branch prohibited) ``` The repository's default branch cannot be deleted, protected or not, because clones start from it. An owner can pick another default branch in the repository's settings first. ## Rate, size and ref limits ``` ! [remote rejected] main -> main (rate limited: 300 pushes in the last hour (limit 300)) ! [remote rejected] main -> main (rate limited: 20,000 pushes to this organization today (UTC); retry tomorrow) ! [remote rejected] main -> main (repository is over its 5 GB limit) ! [remote rejected] topic -> topic (repository has too many refs (limit 100,000)) ``` A repository takes at most 300 pushes an hour and 5,000 a day, holds at most 5 GB and 100,000 branches and tags. All repositories of an organization together take at most 20,000 pushes a day (UTC). Wait before pushing again, or delete branches and tags you no longer need. ## Read-only repository ``` ! [remote rejected] main -> main (repository is read-only: pushes are paused) ! [remote rejected] main -> main (repository is read-only: integrity check failed) ``` Rebasely paused pushes to this repository. The reason after the colon says why: `pushes are paused`: Rebasely paused pushes for maintenance or an incident. Clones and fetches still work, and pushes resume without anything for you to do. `integrity check failed`: real git rejected objects already pushed to the repository. Until the Rebasely team has reviewed it, clones and fetches are paused too, except for owners of the organization, who got an email and can still clone and fetch their work with an access token. Nothing was deleted. git may print `remote: This repository is read-only.` instead, before it sends anything. ## Invalid or unsafe objects ``` error: remote unpack failed: error object check failed (hasDotgit) error: remote unpack failed: error invalid pack (truncated) error: remote unpack failed: error missing necessary objects ``` Rebasely checks every object in a push the way `git fsck --strict` does, and also refuses paths that can harm a checkout, such as `.git` look-alikes and unsafe `.gitmodules` entries. The name in parentheses is git's own check. Run `git fsck --strict` in your repository to find the object, and rewrite the commits that contain it. Other limits: an object can be at most 100 MiB, a push at most 1,000,000 objects, and a tree at most 100,000 entries. `missing necessary objects` means the push refers to a commit or file the server does not have; fetch and push again. ## Repository busy ``` ! [remote rejected] main -> main (repository busy, retry) ``` Many pushes reached the repository at the same moment, or the server restarted during the push. Nothing changed. Retry the push. ## Refs outside branches, tags and notes ``` ! [remote rejected] HEAD -> refs/pull/1/head (deny updating a hidden ref) ! [remote rejected] HEAD -> refs/other/x (refusing to update ref outside refs/heads, refs/tags or refs/notes) ``` Pushes can create and update branches (`refs/heads/`), tags (`refs/tags/`) and notes (`refs/notes/`), and update sandboxes (`refs/sandbox/`, below). Other refs are managed by Rebasely. A push also takes at most 1,000 ref updates, and a ref name at most 255 bytes. ## Sandbox branches ``` ! [remote rejected] HEAD -> refs/sandbox/a-fixer/try (sandbox does not exist: create it with rebasely sandbox create) ! [remote rejected] HEAD -> refs/sandbox/a-other/try (sandbox belongs to another owner) ! [remote rejected] HEAD -> refs/sandbox/a-fixer/try (sandbox is expired) ``` A sandbox (`refs/sandbox//`) is created with `rebasely sandbox create` or the API, never by a push, and only its owner (or an owner of the repository) pushes to it. One without a push for its time to live expires; create a new one. See [sandboxes](https://rebasely.com/docs/sandboxes) for the whole flow, and the [Rebasely agent skill](https://rebasely.com/docs/skills/rebasely/SKILL.md) for agents. ## Live branches ``` ! [remote rejected] feature -> feature (live branch moved: fetch first) ! [remote rejected] feature -> feature (live branch: force-push not allowed (disable live first)) ! [remote rejected] feature (live branch: disable live first) ! [remote rejected] feature -> feature (live branch busy, retry) ``` The branch is live: people or agents are editing it, and Rebasely commits their edits as checkpoints. Pull the latest checkpoint and push again. Force-pushes and deletes are refused until a writer turns live off for the branch. [How pushes and live edits fit together](https://rebasely.com/docs/live#git). --- Source: https://rebasely.com/docs/errors # Git LFS Rebasely does not support Git LFS. A repository that uses it cannot push its large files here: git-lfs gets an error from Rebasely for every LFS request. ## What to do - Turn off the LFS hooks in a clone that should push to Rebasely: `git lfs uninstall --local`. - Keep large files out of the repository: build artifacts, datasets and media belong in object storage or a package registry, with the repository holding a script or a manifest that fetches them. - To bring a repository that already tracks files with LFS, convert them back to ordinary git objects first (`git lfs migrate export --everything --include="*"`), keeping in mind Rebasely's push limits. ## Questions - Security vulnerabilities: [security@rebasely.com](mailto:security@rebasely.com) - Abuse, spam and illegal content: [abuse@rebasely.com](mailto:abuse@rebasely.com) - Copyright (DMCA) notices: [dmca@rebasely.com](mailto:dmca@rebasely.com) (see [the DMCA policy](https://rebasely.com/dmca)) --- Source: https://rebasely.com/docs/lfs # Actions Rebasely Actions runs your CI on every push and pull request. Workflows live in `.rebasely/workflows/`, each job runs in its own Cloudflare Sandbox, and every job reports a check on the commit. *Diagram: A push or a pull request event starts the workflows in .rebasely/workflows that match it. Each job of the run gets its own Cloudflare Sandbox: it checks out the commit, runs the steps and streams its log live, with secrets masked. Each job reports a commit status, which pull requests show as checks and protected branches can require.* *An event starts the matching workflows; each job runs in a fresh sandbox and reports a status on the commit.* ## Your first workflow ### 1. Add a workflow file Create `.rebasely/workflows/ci.yml`: ```yaml name: ci on: push: branches: ["**"] pull_request: branches: [main] jobs: test: runs-on: { image: node24, instance: lite } steps: - uses: duragit/checkout@v1 - uses: duragit/cache@v1 with: key: npm key-files: [package-lock.json] paths: [~/.npm] - run: npm ci - run: npm test ``` ### 2. Push it ```sh git add .rebasely/workflows/ci.yml git commit -m "Add CI" git push ``` ### 3. Watch the run The repository's Actions tab lists the run; a job's page streams its log live. From a terminal: ```sh rebasely runs list rebasely runs logs --follow ``` A repository that still has a `.duragit/workflows` folder keeps working: Rebasely reads `.rebasely/workflows` when it exists, and the old folder otherwise. ## When workflows run | Event | Runs on | | --- | --- | | `push` | Pushes to branches and tags, filtered by `branches`, `tags` and `paths`. Live-branch checkpoints only with `checkpoints: true`. | | `pull_request` | Opening, reopening and pushing to a pull request, on the result of the merge. [Checks on pull requests](https://rebasely.com/docs/pull-requests#checks). | | `schedule` | A cron, in UTC, at most every 5 minutes, on the default branch. | | `workflow_dispatch` | By hand: the Run a workflow form, `rebasely dispatch` or the API, with inputs. | | `sandbox` | A [sandbox](https://rebasely.com/docs/sandboxes)'s checks, on request. Never with secrets. | `git push -o ci.skip` starts nothing. [Workflow syntax](https://rebasely.com/docs/workflow-syntax#on) has every filter. ## Runners: images and instances Each job starts a fresh container from its image on Cloudflare Sandboxes (Linux, x86\_64), works in `/workspace`, and is gone when the job ends. `runs-on` picks the image and the instance; the default is `node24` on `basic`. | Image | What it has | | --- | --- | | `node24` | Node.js 24, npm, corepack, git, curl, jq, tar, unzip and the usual shell tools (the default) | | `gitbox` | git and Node.js, small | | `builder` | Go, Python, Node.js, build tools, apko and crane (standard-1 or larger) | | `deploy` | Node.js 24 and wrangler, for `duragit/wrangler@v1` (standard-1 or larger) | | Instance | vCPU | Memory | Disk | | --- | --- | --- | --- | | lite | 1/16 | 256 MiB | 2 GB | | basic | 1/4 | 1 GiB | 4 GB | | standard-1 | 1/2 | 4 GiB | 8 GB | | standard-2 | 1 | 6 GiB | 12 GB | | standard-3 | 2 | 8 GiB | 16 GB | | standard-4 | 4 | 12 GiB | 20 GB | > **Note:** More images (Python, Go, Rust, Java) are planned; a workflow that names one today fails with "not available yet". On the free plan the largest instance is standard-1 and a job runs at most 60 minutes. ## Secrets Add secrets to an organization, a repository or a deployment environment in their Actions settings (it needs a recent confirmation with Google or a passkey). Values are write-only: nobody can read one back. A step gets a secret only when it names it: ```yaml - run: ./deploy.sh env: API_TOKEN: ${{ secrets.API_TOKEN }} ``` - An environment's secret wins over the repository's, which wins over the organization's. - A secret can instead be bound to a host: the job sees a placeholder, and Rebasely adds the real value only to requests to that host. - Values are masked in logs; write more values to mask, one per line, to `$DURAGIT_MASK`. - Runs started by people who are not established writers, and every sandbox run, get no secrets. ## Who can start what A run is trusted when whoever started it is an established writer of the organization (an account 7 days old or verified). For a pull request, its author and everyone who pushed to it must be. An untrusted run waits until a different established writer approves it, at that commit, and then runs without secrets, without pushing, and on at most a basic instance. ## Network By default a job reaches the package registries it needs (npm, PyPI, crates.io, the Go proxy, Debian and Wolfi packages) for reading only. List more hosts under a job's `egress`; that needs a verified owner or a paid plan. ## Checks, logs and artifacts - Each job reports a commit status named `duragit//`. Pull requests show them as checks, and [branch protection](https://rebasely.com/docs/pull-requests#protection) can require them. - Logs stream live and are kept 30 days on the free plan; a job's log is cut at 64 MiB. - `duragit/upload-artifact@v1` keeps files for 30 days; `duragit/cache@v1` reuses dependencies between runs. - Cancel a run from its page or with `rebasely runs cancel `. A job that failed because of Rebasely itself is retried once. CLI: ```sh rebasely runs list --branch main rebasely runs logs --job test --follow rebasely dispatch deploy.yml --ref main --input target=staging ``` API: ``` GET /api/v1/repos///actions/runs POST /api/v1/repos///actions/runs//cancel POST /api/v1/repos///actions/workflows/deploy.yml/dispatches ``` --- Source: https://rebasely.com/docs/actions # Workflow syntax The keys of a workflow file in `.rebasely/workflows/`. It is close to GitHub Actions' syntax, with a smaller and stricter set of keys: a file with a key Rebasely does not know fails with the line and column, before any job starts. > **Not GitHub Actions:** Differences from GitHub Actions: only Rebasely's built-in actions (`duragit/*@v1`) can be used, `${{ }}` is never allowed inside `run:` (pass values through `env:`), steps always run as `bash -eo pipefail` in `/workspace`, and the context is `duragit`, not `github`. ## The file | Key | What it is | | --- | --- | | `name` | The workflow's name, shown in the Actions tab | | `on` | What starts it (required): an event, a list of events or a map of them | | `env` | Variables for every job | | `concurrency` | A group name, or `{group, cancel-in-progress}`: one run of the group at a time | | `jobs` | The jobs, by id (at least one) | Plain YAML only: anchors, aliases, tags and duplicate keys are refused. At most 20 files per repository, 64 KiB each. ## on ```yaml on: push: branches: [main, "release/**"] tags: ["v*"] paths: ["src/**", "!src/**/*.md"] checkpoints: false # live-branch checkpoints, at most once every 5 minutes pull_request: branches: [main] # the base branch types: [opened, synchronize, reopened] rerun-on-base-change: true schedule: - cron: "30 4 * * 1-5" # UTC workflow_dispatch: inputs: target: { type: choice, options: [staging, production], default: staging } sandbox: paths: ["src/**"] ``` - Patterns: `*` within one part of a path, `**` across parts, `!` to exclude; later patterns win. Use `branches-ignore`, `tags-ignore` and `paths-ignore` instead of `!` if you prefer, but not both for the same filter. - `pull_request` types are `opened`, `synchronize` and `reopened`; `closed` is refused for now. - Schedules: at most 5 per workflow, at most every 5 minutes. A scheduled run uses the default branch's latest commit. - `workflow_dispatch` inputs are `string`, `choice`, `boolean` or `number`, at most 25. Steps see them as `DURAGIT_INPUT_`. ## Jobs ```yaml jobs: test: runs-on: { image: node24, instance: standard-1 } timeout-minutes: 30 strategy: matrix: node-env: [development, production] env: NODE_ENV: ${{ matrix.node-env }} steps: - uses: duragit/checkout@v1 - run: npm ci && npm test deploy: needs: test if: duragit.ref == 'refs/heads/main' environment: production runs-on: { image: deploy, instance: standard-1 } steps: - uses: duragit/checkout@v1 - uses: duragit/wrangler@v1 with: args: [deploy] env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} ``` | Key | What it is | | --- | --- | | `runs-on` | An image, or `{image, instance}`; default `node24` on `basic` | | `needs` | Jobs that must finish first | | `if` | A condition; the job is skipped when it is false | | `timeout-minutes` | 1 to 350, default 60, and at most the plan allows | | `strategy.matrix` | Axes, `include` and `exclude`; at most 64 combinations | | `environment` | A deployment environment, with its rules and approvers | | `concurrency` | One job of the group at a time | | `permissions` | `contents: read\|write` (write lets a trusted job push) and `statuses: write\|none` | | `egress` | More hostnames the job may reach | | `env`, `outputs`, `steps` | Variables, values for jobs that need this one, and the steps (at most 100) | Not supported: `services`, `container`, `defaults`, reusable workflows, and `fail-fast` or `max-parallel` in a strategy. ## Steps | Key | What it is | | --- | --- | | `run` | A bash script, run with `bash -eo pipefail` in `/workspace` | | `uses`, `with` | A built-in action and its inputs | | `id`, `name`, `if`, `env` | An id for its outputs, a name, a condition, variables | | `timeout-minutes`, `continue-on-error` | A shorter deadline; keep going when it fails | A step sets outputs by appending `name=value` lines to `$DURAGIT_OUTPUT`; later steps read them as `steps..outputs.`. ## Built-in actions | Action | What it does | | --- | --- | | `duragit/checkout@v1` | Checks out the commit. `fetch-depth` (1 by default, 0 for all history), `filter`, `path`, `submodules`, `ref` (a full SHA of this repository). | | `duragit/cache@v1` | Restores and saves directories by `key` and `key-files`; `paths` is required. Output `cache-hit`. | | `duragit/upload-artifact@v1` | Keeps files from the run: `name`, `path`, `if-no-files-found`. | | `duragit/download-artifact@v1` | Gets an artifact of the same run. | | `duragit/wrangler@v1` | Runs wrangler with `args`, on the `deploy` image. | ## Expressions `${{ }}` works in `if`, `env` and `with` values, `name`, `outputs`, `concurrency` and the image of `runs-on`. The contexts are `duragit`, `inputs`, `matrix`, `needs`, `steps`, `env` and `secrets` (in `env` and `with` only). Functions: `contains`, `startsWith`, `endsWith`, `format`, `join`, `toJSON`, `fromJSON`, `success`, `failure`, `always` and `cancelled`. `duragit` has `event`, `ref`, `ref_name`, `ref_type`, `sha`, `before`, `repository`, `org`, `actor`, `workflow`, `default_branch`, `run_id` and, for pull requests, `pull_request` (`number`, `head_ref`, `head_sha`, `base_ref`, `base_sha`). ## Variables a step sees `CI=true`, `DURAGIT_ACTIONS=true`, `DURAGIT_EVENT`, `DURAGIT_REF`, `DURAGIT_SHA`, `DURAGIT_BEFORE`, `DURAGIT_ACTOR`, `DURAGIT_REPOSITORY`, `DURAGIT_WORKFLOW`, `DURAGIT_JOB`, `DURAGIT_RUN_ID`, `DURAGIT_ATTEMPT`, `DURAGIT_WORKSPACE`, `DURAGIT_OUTPUT` and `DURAGIT_MASK`; on pull requests also `DURAGIT_PR_NUMBER`, `DURAGIT_HEAD_REF`, `DURAGIT_HEAD_SHA`, `DURAGIT_BASE_REF` and `DURAGIT_BASE_SHA`. Names starting with `DURAGIT_` are reserved. --- Source: https://rebasely.com/docs/workflow-syntax # Sign-in, passkeys and confirmation You sign in to Rebasely with Google. Before a sensitive action, Rebasely asks you to confirm it's you, with a fresh Google sign-in or a passkey. Passkeys are optional. ## Signing in Rebasely uses Google as its only way to sign in, so it never stores a password for you. A new account accepts the terms of service and the acceptable use policy first. Rebasely lets a limited number of new people in each day; past that, you join the waitlist and get an email when your place opens. ## Confirming it's you Some actions need a recent confirmation, even when you are signed in: - creating an access token or adding an SSH key; - making a repository public, changing branch protection and other repository and organization settings; - Actions secrets and deployment environments; - creating and managing agents, and approving requests on [/approve](https://rebasely.com/approve); - renaming, transferring or deleting a repository, an organization or your account, and starting a data export. ### 1. Rebasely asks The action takes you to a Confirm it's you page, and back to where you were afterwards. ### 2. You confirm Choose **Continue with Google** and sign in to the same Google account again, or use a passkey if you added one. ### 3. It lasts 2 hours The confirmation covers this browser session for 2 hours after you last confirmed. ## Passkeys A passkey confirms it's you with one touch (Touch ID, Windows Hello, a security key or your phone) instead of a Google sign-in. Add one on your [account page](https://rebasely.com/account); adding it needs a confirmation too. Passkeys are optional: everything works with Google alone, and you can dismiss the reminder to add one. > **Tip:** Passkeys made on duragit.com before the rename keep working on rebasely.com in browsers that support related origins. In others, Rebasely sends you to confirm on the old host once and offers a new passkey for rebasely.com. ## Sessions A session ends after 14 days without use, and after 30 days in any case. Your [account page](https://rebasely.com/account) lists your sessions; end one there, or **Sign out everywhere** to end all of them, including on other devices. SSH keys added before you sign out everywhere stop working too. ## New accounts Until an account is 7 days old, or verified, it cannot make a repository public, write to live branches or turn live on, approve Actions runs or have the server write merge commits, and its pushes are checked more closely. It can still turn live off on a branch it can write to. This keeps throwaway accounts from abusing Rebasely; nothing changes for you after the first week. ## Your data Download everything Rebasely stores about you from [Your data](https://rebasely.com/account/export), or delete your account there. The [privacy notice](https://rebasely.com/privacy) says what is kept and for how long. To report a security problem, email security@rebasely.com ([details](https://rebasely.com/security)). --- Source: https://rebasely.com/docs/sign-in # Access tokens and scopes git, the CLI, the API and MCP sign in with an access token. Each token has scopes, belongs to one organization, the ones you pick from the CLI, or all of them, can be limited to some repositories, and always expires. ## Personal and agent tokens | Token | Starts with | Made by | Expires | | --- | --- | --- | --- | | Personal | `dgp_` | You, at [/settings/tokens](https://rebasely.com/settings/tokens), or `rebasely auth login` | after 1 to 365 days (90 by default), or after a year unused | | Agent | `dga_` | An owner, for an [agent](https://rebasely.com/docs/agents) | after at most 90 days (30 by default) | A token is shown once, when it is made; Rebasely keeps only a hash. You get an email a week before one expires. Creating a token needs a [recent confirmation](https://rebasely.com/docs/sign-in#confirm), and no token can create another. ## Scopes | Scope | Allows | | --- | --- | | `repo:read` | Clone, fetch and read repositories | | `repo:write` | Push, open, review and merge pull requests, and use sandboxes (includes repo:read) | | `repo:create` | Create private repositories | | `repo:admin` | Repository settings (owners only) | | `org:admin` | Organization settings (owners only) | | `actions:read`, `actions:write` | Read runs and logs; start and cancel runs | | `statuses:write` | Post commit statuses | | `live:read`, `live:write` | Read and edit live branches | | `sandbox:write` | Sandboxes (agents only; a person's token uses repo:write) | A token never does more than its owner's role allows: a reader's token can only read. `rebasely auth login` asks for `repo:read`, `repo:write`, `repo:create`, `live:read` and `live:write` by default, and never for the admin scopes. ## Tokens for all your organizations A personal token can work in every organization you belong to instead of a fixed list. Pick "All organizations you belong to" in the token form, or run `rebasely auth login --all-orgs` and keep that choice on the approval page. - It covers the organizations you are a member of when each request arrives: one you join later is included, one you leave is not. Changes take effect within 30 seconds. - In each organization it acts with your role there. A scope your role does not allow does nothing: `repo:admin` or `org:admin` works only where you are an owner, `repo:create` and `repo:write` only where you are a writer or owner. - Your scopes must be ones some role you hold allows when you create it. It cannot be limited to repositories. - Making a repository public, and everything else that needs an owner's approval, still goes through an [approval](https://rebasely.com/docs/agents#approvals) confirmed with a passkey or Google. - It expires after 90 days unless you pick fewer, and never after more than 365. - Agent tokens are always for one organization and can never be for all of them. Your token list shows these tokens as "All organizations", with when and in which organization each was last used. The audit log of each organization records what the token did there. An owner of one of your organizations sees the token in that organization's token list and can remove their organization from it; it keeps working in your other organizations. Revoking it yourself, or signing out everywhere, ends it everywhere. ## Using a token with git ```sh rebasely auth login # approve in the browser; git's credential helper keeps it rebasely auth login --all-orgs # one token for every organization you belong to, now and later rebasely auth status # the account, organizations, scopes and expiry rebasely auth logout # revoke it and remove it from the helper ``` Without the CLI, paste the token when git asks for a password (any user name works). For scripts and agents, put it in `REBASELY_TOKEN`; the CLI sends it only to Rebasely's own hosts. In API calls, send `Authorization: Bearer ` to `https://rebasely.com/api/v1`. ## When a token leaks into a push > **Warning:** If a push contains an active Rebasely token, Rebasely refuses the push, revokes the token at once and emails its owner. Remove it from every commit of the push, create a new token and keep it out of the repository. The same happens to the private half of a registered SSH key, which is then blocked for good. Revoke a token any time at [/settings/tokens](https://rebasely.com/settings/tokens). Owners see and revoke the tokens of their organization in its settings. --- Source: https://rebasely.com/docs/tokens