# Team admin

A team is a git repository. Administering it means editing files in that repository or asking your git host to change who can reach it, with no server and no Terum account in between.

## Members and admins

**Membership is two facts in the repository.** A member has a `people/<handle>.json` file, and their handle is not in the `archived` list in `team.json`. `status` reports your own as active, inactive (archived) or no entry.

**Admin is not a Terum role.** It is GitHub repository admin permission, checked with GitHub at the moment it matters. `status --permissions` makes one network call to mark which roster entries are admins; without it, admin state is unknown. `profile --role` is only a label of up to 32 characters, and it grants nothing.

## Inviting people

```sh
npx -y terum-skills@latest invite ada grace
```

Invitations are GitHub only; on any other host the command refuses before sending anything. You need repository admin permission. The CLI does not check it first: GitHub answers a non-admin with a `403` for each login.

The whole batch is validated before a single invitation goes out, so a malformed login stops the run with nothing sent, and duplicates are dropped. GitHub caps invitations at 50 per repository per day, and waiting is the only fix. The request names no permission level, so GitHub applies its default for a new collaborator.

At the end the CLI prints a block to send your teammate. Its core is the setup command, which tries to accept their pending invitation through `gh`, or asks them to accept it in the browser:

```sh
npx -y terum-skills@latest setup acme/skills
```

## Removing someone

```sh
npx -y terum-skills@latest team remove ada-handle
```

On GitHub this needs repository admin permission, checked before anything is asked. It refuses to remove yourself, a handle that is not on `origin/main`, the last admin, or a login that another active member also declares.

**The roster is archived first, then access is revoked.** One commit adds the handle to `archived`. Their people file and every skill they published stay: membership changes, history does not. Then GitHub removes them as a collaborator and cancels any pending invitation. If the revocation fails after the archive landed, run the same command again; that half is safe to retry.

`--archive-only` archives the membership and leaves host access alone (on GitHub it still needs admin permission). It is the only form that works off GitHub, and the only one for a roster entry with no GitHub login.

## Leaving or moving a machine

```sh
npx -y terum-skills@latest team leave acme
```

`team leave` is machine-local. It writes nothing to the team repository, and your membership is unchanged. It removes every skill placed from that team (quarantining any copy you edited), the clone and the team's config entry. A clone with uncommitted or unpushed work is quarantined, never deleted. Leaving the last team also removes the session-start hook and clears your tool-grant answers.

```sh
npx -y terum-skills@latest team move acme/shared-skills
```

`team move` follows a repository that was recreated under a new name. It tears the old team down locally, joins the target, then places again every skill the new team also shares, at the same scope. The old repository is never touched, and a skill the new team lacks is reported. `sync` offers this move by itself when a GitHub team's repository answers "repository not found".

## Profiles and team projects

### Identity and profile

Your identity is per machine, and it is what `publish` writes into a skill's author line:

```sh
npx -y terum-skills@latest login --set name="Ada Lovelace" --set email=ada@example.com
```

The only keys are `name`, `email` and `default-handle`. Versions already published keep the author they were minted with.

Your profile is per team and lives in your people file. `profile` sets `--name`, `--bio`, `--role` and `--project`, and `--remove <skill>` takes an entry off your `profile[]` list. It refuses to change `email`, `github` or `handle`, which join binds. `profile[]` is what teammates install with `install member <handle>`. Publishing and installing each add an entry without asking, and removing one never unpublishes anything.

### Team projects

A team project is a named list of skills in `team.json`, with the repositories it belongs to. It is not a folder, and creating one moves no skill. A repository belongs to exactly one project.

```sh
npx -y terum-skills@latest team project create docs-site --remote https://github.com/acme/web
```

Skills enter a project one way, `publish <skill> --project docs-site`, and teammates take the whole list with `install project docs-site`. Nothing places a project's skills automatically, whatever `create` prints: the repository only preselects the matching registered project as the install destination. `team project delete` removes the list and never a skill.

## Status and migration

`status` shows what this machine thinks the team is, and reads only local files (`--permissions` adds one network call). A clean exit means the query worked, not that the team is reachable.

`team migrate` brings a team repository to layout 3. Run it once, from a terminal, after every teammate has a CLI that understands layout 3, because older CLIs reject the new layout. It validates everything before writing, and leaves a repository it cannot migrate cleanly exactly as it was. See [Migrating to layout 3](https://github.com/ryanliu-terum/terum-skills/blob/main/docs/migration-layout-3.md).

## Teams on other git hosts

Storage works on any git remote. Access management needs GitHub's collaborator API.

| Works anywhere | GitHub only |
| --- | --- |
| Creating, joining, publishing, unpublishing, installing, syncing | `invite` |
| `team remove --archive-only` | `team remove` without `--archive-only` |

`team create --remote <url>` needs an empty repository you already have credentials for. No `gh` login is needed on either side: git uses your ordinary credentials. Add and remove people on the host itself, then archive a roster entry with `team remove <handle> --archive-only` or restore one with `team join`. With no GitHub Action to regenerate the `README.md` catalog, the CLI rebuilds it inside each commit it makes.
