# binSource for AI coding assistants

For AI coding assistants (Claude Code, Cursor, Codex and similar). If the human you work for has given you a binSource token in the environment variable `BINSOURCE_TOKEN`, you can put the project you are working on under version control yourself: check what already exists on binSource, create the missing organization and private repository, and push. **Do not ask the human to click anything in the web interface.**

This document has two parts:

- **Autonomous mode (A1–A5)**: what to do, in order. Read this first.
- **Reference (1–7)**: endpoints, status codes, naming rules, and setup instructions for humans.

| | |
|---|---|
| This guide | `https://forai.binsource.com` (Markdown: `https://forai.binsource.com/llms.txt`) |
| Website | `https://www.binsource.com` |
| API base | `https://www.binsource.com/api/v1` |
| API auth | header `Authorization: token $BINSOURCE_TOKEN` |
| Git | HTTPS only. SSH is not available. |
| Git auth | HTTP Basic, user = your login, password = the token (see A4) |
| API explorer | `https://www.binsource.com/api/swagger` |

---

## A1. Start here

1. **Check the token.** If `BINSOURCE_TOKEN` is empty, stop and tell the human to follow section 7. Otherwise find out whose token it is:

   ```bash
   curl -fsS -H "Authorization: token $BINSOURCE_TOKEN" https://www.binsource.com/api/v1/user
   ```

   The `login` field is the account you act for. A `401` means the token is wrong or revoked; stop and tell the human.

2. **Decide the target** `owner/repo` with the decision tree in A2.
3. **Make sure the owner and the repository exist**, creating them if needed (A3).
4. **Commit and push** (A4).
5. **Record the target** in the project's `CLAUDE.md` so later sessions push to the same place (A2, step 4).

### Rules

These are hard rules. The token technically allows more; you must not do it.

- **Never delete** anything on binSource: organizations, repositories, branches, tags or releases.
- **Never force-push** (`--force`, `--force-with-lease`, `+refspec`) unless the human explicitly asks for it in the current conversation.
- **Never change the visibility** of an existing repository or organization.
- New repositories are always **private**. New organizations are created with visibility **private**.
- **Never write the token** into a remote URL, `.git/config`, a file in the repository, a commit, a commit message, or a log you show. Pass it per command (A4).
- **Check for secrets before the first push.** Do not push `.env` files, private keys, credential files or database dumps. Add them to `.gitignore` instead.
- **One project, one repository.** Push only the project directory you are working in.
- Push only to the owner chosen in A2. Never push to repositories of other users.

---

## A2. Decision tree: which owner and repository

Go through the steps in order and stop at the first one that gives an answer.

1. **Existing remote.** If `git remote -v` shows a remote on `www.binsource.com`, use its `owner/repo`.
2. **Project instructions.** If `CLAUDE.md` or `AGENTS.md` in the project contains a line `binsource: <owner>/<repo>`, use it.
3. **Derive it.** Each project goes into an organization named after its brand or client:
   - **Organization**: the brand, client or product family the project belongs to. Use the first clear source:
     1. a company or client name stated in the README or docs;
     2. the production domain without the TLD (`shop.acme.cz` → `acme`);
     3. package metadata: npm scope (`@acme/web` → `acme`), Composer vendor (`acme/web` → `acme`), Go module path, Java group id.

     If nothing identifies a brand or client, use the project slug as the organization name.
   - **Before creating an organization**, list the ones the account already has (`GET /user/orgs`) and reuse one that clearly matches, for example `acme` rather than a new `acme-cz`.
   - **Repository**: the project directory name.
   - Turn both into slugs (see reference 4).
4. **Record the decision.** Add this line to the project's `CLAUDE.md` (create the file if it does not exist) and commit it with the project:

   ```
   binsource: acme/webshop
   ```

---

## A3. Make sure the organization and repository exist

Every step is safe to repeat.

```bash
set -eu
API=https://www.binsource.com/api/v1
AUTH="Authorization: token $BINSOURCE_TOKEN"
OWNER=acme                 # from A2
REPO=webshop               # from A2
DESC="Online shop for Acme" # one line, no double quotes

LOGIN=$(curl -fsS -H "$AUTH" "$API/user" | sed -n 's/.*"login":"\([^"]*\)".*/\1/p')

# Organization (skip when pushing to the personal account)
if [ "$OWNER" != "$LOGIN" ]; then
  code=$(curl -sS -o /dev/null -w '%{http_code}' -H "$AUTH" "$API/orgs/$OWNER")
  if [ "$code" = 404 ]; then
    curl -fsS -X POST -H "$AUTH" -H 'Content-Type: application/json' "$API/orgs" \
      -d "{\"username\":\"$OWNER\",\"visibility\":\"private\"}" >/dev/null
  fi
fi

# Repository
code=$(curl -sS -o /dev/null -w '%{http_code}' -H "$AUTH" "$API/repos/$OWNER/$REPO")
if [ "$code" = 404 ]; then
  if [ "$OWNER" = "$LOGIN" ]; then url="$API/user/repos"; else url="$API/orgs/$OWNER/repos"; fi
  curl -fsS -X POST -H "$AUTH" -H 'Content-Type: application/json' "$url" \
    -d "{\"name\":\"$REPO\",\"private\":true,\"default_branch\":\"main\",\"description\":\"$DESC\"}" >/dev/null
fi
```

When something fails:

| Situation | Meaning | What to do |
|---|---|---|
| `POST /orgs` returns `422` | The name belongs to another user or organization you cannot see | Choose a more specific name (for example `acme-web`), then go back to A2 step 4 |
| `GET /orgs/{org}` returns `200` but `POST /orgs/{org}/repos` returns `403` | The organization exists but the account is not an owner of it | Do not push there. Pick another organization name |
| `POST …/repos` returns `409` | The repository already exists | Continue with A4 |
| `403` with a message about scopes | The token lacks a permission | Tell the human which scope is missing (reference 1) |

---

## A4. Commit and push

```bash
BS=https://www.binsource.com
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || git init -b main

# Remote: use "origin" if the project has none, otherwise "binsource"
if ! git remote -v | grep -q "www.binsource.com/$OWNER/$REPO"; then
  if git remote get-url origin >/dev/null 2>&1; then R=binsource; else R=origin; fi
  git remote add "$R" "$BS/$OWNER/$REPO.git"
fi
R=$(git remote -v | awk -v u="www.binsource.com/$OWNER/$REPO" '$2 ~ u {print $1; exit}')

# Local identity only if none is configured; never change global git config.
# The email from GET /user links the commits to the account on binSource.
EMAIL=$(curl -fsS -H "$AUTH" "$API/user" | sed -n 's/.*"email":"\([^"]*\)".*/\1/p')
git config user.email >/dev/null || git config user.email "$EMAIL"
git config user.name  >/dev/null || git config user.name  "$LOGIN"

git add -A
git diff --cached --quiet || git commit -m "Describe what changed"

BASIC=$(printf '%s:%s' "$LOGIN" "$BINSOURCE_TOKEN" | base64 | tr -d '\n')
git -c http.extraHeader="Authorization: Basic $BASIC" push -u "$R" HEAD
```

- Write a real commit message that describes the change. `auto sync` is not a commit message.
- Use the same `-c http.extraHeader=…` for `fetch` and `pull`.
- If the push is rejected as non-fast-forward, run `fetch` and then rebase or merge. Do not force-push.
- Files over about 50 MB belong in Git LFS (`git lfs track`), which binSource supports.

---

## A5. Releases (optional)

When the human asks for a release, tag the commit and create a release:

```bash
git tag -a v1.2.0 -m "v1.2.0"
git -c http.extraHeader="Authorization: Basic $BASIC" push "$R" v1.2.0
curl -fsS -X POST -H "$AUTH" -H 'Content-Type: application/json' \
  "$API/repos/$OWNER/$REPO/releases" \
  -d '{"tag_name":"v1.2.0","name":"v1.2.0","body":"What changed in this version"}'
```

---

## Reference

### 1. Authentication and token scopes

The token is a personal access token of one binSource account. Everything you create belongs to that account or to its organizations.

| Use | How to send it |
|---|---|
| API | `Authorization: token <token>` |
| Git over HTTPS | HTTP Basic: user `<login>`, password `<token>` |

Scopes the token needs:

| Scope | Why |
|---|---|
| `read:user` | `GET /user` to find the login |
| `write:organization` | create organizations, list the account's organizations |
| `write:repository` | create repositories, push, tags, releases |

### 2. Endpoints

| Method | Path | Purpose |
|---|---|---|
| `GET` | `/user` | The account behind the token (`login`, `email`) |
| `GET` | `/user/orgs` | Organizations of the account |
| `GET` | `/user/repos` | Repositories the account can access |
| `GET` | `/orgs/{org}` | Does the organization exist and is it visible to you |
| `POST` | `/orgs` | Create an organization: `{"username": "acme", "visibility": "private"}` |
| `GET` | `/repos/{owner}/{repo}` | Does the repository exist and is it visible to you |
| `POST` | `/orgs/{org}/repos` | Create a repository in an organization |
| `POST` | `/user/repos` | Create a repository in the personal account |
| `GET` | `/repos/{owner}/{repo}/branches` | List branches |
| `POST` | `/repos/{owner}/{repo}/releases` | Create a release |

Body for creating a repository:

```json
{
  "name": "webshop",
  "description": "Online shop for Acme",
  "private": true,
  "default_branch": "main"
}
```

The full API is described at `https://www.binsource.com/api/swagger`.

### 3. Status codes

| Code | Meaning |
|---|---|
| `200`, `201` | OK, created |
| `401` | Missing, wrong or revoked token |
| `403` | The token lacks a scope, or the account has no rights in that organization |
| `404` | Does not exist, or exists but is not visible to this account. Private repositories of other accounts also return `404` |
| `409` | Repository already exists |
| `422` | Invalid input, or an organization/user with that name already exists |

### 4. Naming rules

- Slug: lowercase `a–z`, digits and `-`. Replace spaces, dots and underscores with `-`, remove diacritics (`Účetnictví` → `ucetnictvi`), collapse repeated `-`, trim `-` at both ends.
- Organization: at most 40 characters. Repository: at most 100 characters.
- Do not start a name with `-` or `.`, and do not end a repository name with `.git`.

### 5. What the human sees

Organizations and repositories you create appear in the human's account on `https://www.binsource.com` right away, under the organization menu. Everything is private unless the human changes it.

### 6. Limits

- Push size is not artificially limited, but keep binaries and large assets in Git LFS.
- There is no separate rate limit for normal use. Do not poll the API in loops.

### 7. For humans: giving an agent access

1. Open **https://www.binsource.com/user/settings/applications?forai=1** (sign in if asked). The form opens with a token name and the right permissions already selected: **organization: Read and Write**, **repository: Read and Write**, **user: Read**.
2. Click **Generate Token**.
3. The page then shows the two snippets below with your token filled in, each with a Copy button. The token is shown only once.
4. Give it to the agent as an environment variable. For Claude Code, add it to `~/.claude/settings.json`:

   ```json
   {
     "env": { "BINSOURCE_TOKEN": "paste-the-token-here" }
   }
   ```

5. Tell the agent where the instructions are. In Claude Code, add this line to `~/.claude/CLAUDE.md` so it applies to every project:

   ```
   Version control: projects are hosted on binSource. When a project has no git remote, or when I ask you to save or upload a project, follow https://forai.binsource.com/llms.txt using the token in $BINSOURCE_TOKEN.
   ```

To revoke access, delete the token on the same Settings → Applications page. Anything the agent created stays in place.
