runlot
Code

Repositories

Git repositories that Runlot hosts itself. You clone and push to our domain, and access follows your organization roles.

Runlot hosts Git repositories. This is not a GitHub integration — git clone and git push talk to our address.

cd my-project              # the project directory, where runlot.json lives
runlot repo create app
# my-org/my-project/app created
# origin registered: [email protected]:my-org/my-project/app.git
git push -u origin main

A repository belongs to a project. That is why the address has three parts, <org>/<project>/<repo>, and why a project can have several repositories — an app and an API, a frontend and a worker. Names only have to be unique within the project. Who can read or write follows the organization role.

Getting started

1. Register your public key

runlot key add
# registered ~/.ssh/id_ed25519.pub (ssh-ed25519, SHA256:…)

With no argument it looks for a default key under ~/.ssh. Pass a path to pick a different one: runlot key add ~/.ssh/work.pub.

A key is an identity here, so two people cannot register the same public key. Re-registering a known key is rejected.

Check the fingerprint the first time you connect

If the host fingerprint ssh shows you differs from these, do not continue.

ed25519  SHA256:C7pTddRdCM1JuEbdi+73oBN+sNAZhb1H5t3CJSlyPj4
rsa      SHA256:+6PMLfTVpcjjLOVSWgiRI0nVQ5f9bVl0nuzcJ0EfTfE

2. Create a repository

runlot repo create app          # private by default
runlot repo create app --public # anyone can clone

It is created in the same place runlot deploy and runlot pg work on — the project named by runlot.json in the current directory. If that directory is a Git repository, origin is registered for you. If origin already exists, nothing is changed and the command is printed instead.

3. Push

git push -u origin main

Over HTTPS

You can use HTTPS instead of SSH. Create a token, and paste it when git asks for a password (any username works).

runlot token create laptop            # read and write
runlot token create ci --read-only    # clone only
git clone https://git.runlot.io/my-org/my-project/app.git

HTTPS and SSH are the same address, git.runlot.io, and SSH is on the ordinary port 22 — nothing to add to ~/.ssh/config.

The token value is shown once, when you create it. Keep it then — you cannot read it back. If you lose it, revoke it with runlot token revoke <id> and make a new one.

Pushing with a read-only token is refused with the reason, not made to look like a missing repository.

Commands

CommandWhat it does
runlot repo create <name> [dir]Creates a repository and registers origin (--public)
runlot repo listLists repositories (--json)
runlot repo rename <old> <new>Renames it (admin)
runlot repo visibility <name> <public|private>Changes visibility (admin)
runlot repo delete <name>Deletes it (admin)
runlot repo history <name>Who moved which branch, and how
runlot key add [path] / runlot key list / runlot key rm <id>SSH public keys
runlot token create <name> / runlot token list / runlot token revoke <id>Tokens for HTTPS

runlot repo targets a project. Outside a project directory, pass both --org and --project. key and token are yours, not a project's, and work anywhere.

Who can do what

Private repositoryPublic repository
Organization adminread, write, settingsread, write, settings
Organization memberread, writeread, write
Organization viewerreadread
User in another organizationread
Not signed inread

Permission changes take effect within ten seconds. Deleting a public key or revoking a token takes effect immediately — that is the whole reason those buttons exist.

History

Every push leaves a line. This is how you find a commit lost to a force-push.

runlot repo history app
# 2026-09-09T07:38:30Z	created	refs/heads/main	ae4bb959

Clones and fetches are not recorded.

What works, and what does not yet

Works: clone, fetch, push, branches, tags, force-push, branch deletion.

Not there yet

  • Shallow clone (--depth 1) is not supported. That is a common CI idiom, so this may get in your way.
  • No pull requests, issues, code review, or CI. A repository is a repository.
  • Pushing does not deploy. Deployment is runlot deploy.
  • Backups live on the same machine. A repository you delete by mistake can be brought back, but a machine that disappears takes them with it. What covers you today is Git itself — every developer machine has a full copy.

Browsing on the web

Open the project in the dashboard and use the Repositories tab. You can create a repository, switch branches and tags, and read the file tree, file contents, the commit list, and the ref history — who moved which branch, and how. Admins can rename, change the default branch or visibility, and delete a repository from its Settings tab. The Clone button gives the HTTPS and SSH addresses.

The screen shows you the limits rather than hiding them: files over 1 MiB and binary files have no preview, and directories list the first 1,000 entries. Clone the repository to read past those.

Limits

ItemValueWhen exceeded
Repository size1 GiBThe push is rejected
One push500 MiBThe push is rejected
One file100 MiBThe push is rejected
Deleting the default branchRejected (you could not undo it)

When you hit a limit, git push prints the reason.

Common problems

Permission denied (publickey) — Check with runlot key list that the key is registered. If you juggle several keys, say which one to use:

Host git.runlot.io
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

non-fast-forward (fetch first) — Somebody pushed in the meantime. Run git pull --rebase and push again, or git push --force if you really mean to overwrite.

Pushing or cloning an old two-part address — addresses now have three parts, <org>/<project>/<repo>. SSH tells you what to fix; HTTPS reports the repository as missing. Point the remote at the new address.

runlot repo list                # shows the current address
git remote set-url origin [email protected]:my-org/my-project/my-app.git

You renamed the repository — update the remote you registered:

git remote set-url origin [email protected]:my-org/my-project/new-name.git

On this page