Skip to main content

Teams and invites

An org is one git repo that rt manages, shared by everyone in it: settings, secrets, skill packs, and forge access, distributed to every member's Mac. Inside the org are teams. Each team is a folder with its own settings and its own skill pack, and the org's settings apply to every team.

A Mac holds one org. Its clone lives at ~/.mattstack/teams/<org>/:

  • mattstack/org/ holds the org's settings, its secrets and its base packs.
  • mattstack/teams/<team>/ holds one team's settings and its pack, under packs/<team>/.

Roles​

The org's mattstack.org setting names who may change what:

  • An admin changes anything in the org: its settings, every team folder, the roster, secrets and invites.
  • A team's owner changes that team's folder: its settings and its pack.
  • A member changes nothing shared. Their Mac only pulls the org.

A change you are not allowed to make is refused before anything is written, with a note naming who to ask: the team's owners, then the org's admins.

Creating an org​

In setup's team step, choose Create a team, give it a name, and leave Others will join later on if teammates will follow. For the repo, paste the URL of an empty repo on GitHub, GitLab, or anything git can push to. When the gh CLI is signed in, you can instead let mattstack create a private GitHub repo under an owner you pick. Setup scaffolds the org under ~/.mattstack/teams/<name>/, and its Install step pushes it.

The org starts with one team inside. That first team takes the org's name, unless you name it with --first-team. You become the org's admin and the first team's owner.

From a terminal:

bash
rt team create Acme --first-team widgets --remote git@github.com:acme/mattstack-team-acme.git # or --create-repo <owner>
rt team publish # push your org changes

--others is the terminal form of Others will join later.

Adding a team​

An admin adds a team with its owners, then puts people on it:

bash
rt team add gadgets --owner dev2
rt team members set dev3 --teams gadgets

rt team add writes the team's folder and pack and shares them with the org.

Inviting a member​

Only an admin invites. Open Settings → Team (or Invite teammates… on setup's last screen), pick the team when the org has more than one, type the teammate's GitHub or GitLab handle, and click Invite…. You get an invite link to copy or share, plus a paste block for chat clients that mangle links, with the invite's expiry and the forge access it grants. When rt can't grant forge access itself, the steps to do it by hand appear underneath.

The link looks like https://mattstack.dev/join#<code>. The code lives in the URL fragment, so it never reaches the join page's server.

From a terminal:

bash
rt team invite --handle dev3 --teams widgets # --teams takes a comma-separated list; your own team when left out

The same pane shows the org's name, your team, the remote, the last push, and your team's members.

What a joiner sees​

The joiner opens the invite link, or pastes the code into Join a team in setup's team step. A Mac holds one org: a join is refused while another org is set up on it, and joining your own org again is fine: Settings → Team → Rejoin this org… takes a new invite from your org admin. The checklist then runs a forge-auth preflight against the org repo:

  • If the joiner's forge account (GitHub or GitLab) cannot see the repo, a warning names the problem and suggests asking for access. The access.team-repo checklist row holds Install until access is resolved.
  • If access is confirmed, setup continues normally.

The invite also carries the joiner's board token. When this Mac's board ends up without one, the Board peering row says the board does not peer yet. It never holds up Install or Finish, but setup keeps listing it, and the setup check after an app update notifies you about it. The fix is on the admin's side: ask them to re-invite your board, with rt team invite --handle <your forge username> (then run rt team join with the new code). The row turns ready once the token arrives. It shows only when your team runs a board, and on the Mac that created the org only when that Mac holds the switchboard admin token, in which case rt team peer connects its board. It shows an error with a Re-check when the switchboard does not answer.

Connecting the admin's board​

A Mac that holds the switchboard admin token connects its own board: rt team create does it for you, and rt team peer does it later, for example when the create could not reach the switchboard. It registers the board under the username this Mac recorded for the org, and leaves a board that already peers alone. On that Mac, the Board peering row's steps name rt team peer. rt team status counts the members with a connected board, and its --json marks each member's board as peered or not.

rt team members remove <handle> removes them from the org and also disconnects their board from the switchboard, so it stops receiving the org's peer traffic. When this Mac cannot disconnect it, the command says so and names who can.

Switching teams​

When the roster puts you on more than one team, pick the one you work as in Settings → Team → Your team, or:

bash
rt team use gadgets

Your settings then read that team's folder over the org's, and its pack is turned on in place of the old one.

When an invitee replies​

While you have outstanding invites, the daemon checks each one for a reply every few minutes and notifies you once per reply. The notification's Add member… action runs rt team members sync, which adds the invitee's key so the org's secrets decrypt for them.

How changes travel​

The daemon keeps each Mac's clone in step with the org repo. It pulls on a timer, and on an admin's or owner's Mac it also commits and pushes the changes that Mac's role owns, such as a rt settings set --scope org or --scope team write, with no hand commit. Packs are the exception: the pack's author commits and pushes a pack's edits, and rt skills sync brings the installed copies current. A member's Mac only pulls, so its clone never drifts from the org's.

Forge grants​

When rt created the org repo itself (via --create-repo), it can manage forge membership on that repo:

bash
rt team manage-membership on # enable automatic grants
rt team manage-membership off # disable

Grant level is read-only: GitHub pull, GitLab Reporter. For repos that rt did not create (pasted --remote URLs), rt grants nothing and prints the forge's member page URL so you can add access manually.

Running rt team invite in a terminal also offers to toggle membership management.

Team packs​

Your team's pack is installed during setup but is not enabled by default. The daemon's snapshot engine converges your team's pack on every pull that moves HEAD: for a pack that is already installed it runs claude plugin update (preserving the disabled state), never install (which would re-enable). Other teams' packs are left alone.

The checklist (Setup status…, or rt setup status) shows a row per team-served pack with its installed version, served version, and the command to enable it.

Pulling now​

bash
rt team pull

Asks the daemon to pull the org clone immediately instead of waiting for its periodic pull. When the pull moves HEAD, your team's pack converges exactly as above.

rt skills sync is for a pack's author: it pulls the pack and engine checkouts, recompiles and pushes a new version when the compiled skills have drifted, and updates the installed plugins. When the mattstack engine is installed from its marketplace rather than a local checkout, sync first updates that installed copy from its marketplace, stops if the update fails, and compiles the pack against it.

Quick reference​

CommandWhat it does
rt team create <name> [--first-team <team>]Start an org with its first team inside
rt team add <team> --owner <user>Admins: add a team with its owners
rt team use <team>Switch which of your teams you work as
rt team publishPush your org changes to the remote
rt team invite --handle <user> [--teams <team>]Admins: mint an invite that puts someone on a team
rt team manage-membership [on|off]Control forge grants on rt-created repos
rt team joinRedeem an invite code
rt team members syncAdmins: collect reply keys from invitees
rt team members set <user> --teams <team>Admins: change which teams someone is on
rt team members remove <user>Admins: revoke access and re-encrypt
rt team statusShow the org and your team
rt team pullPull the clone via the daemon, converging your team's pack if HEAD moved
rt skills syncPack authors: recompile, push, and update a pack's plugins