members.json
members.json defines which UUIDs are distributed and which users receive access to each repository.
The file location is configured via config.json -> members.path.
The canonical member value is the GitLab username. Optional display-name metadata can preserve course-internal or local names without changing the username used for GitLab operations.
Each entry in groups represents one distributed repository group.
Format
{
"version": "2.0",
"displayNames": {
"myname_extern": "myname"
},
"groups": [
{
"uuid": "team-01",
"label": "Team 01",
"metadata": {
"fruit": "banana"
},
"members": ["alice", "myname_extern"]
},
{
"uuid": "team-02",
"label": "Team 02",
"members": ["charlie"],
"unassignedMembers": ["dana"]
}
]
}
Keys
| Key | Type | Notes |
|---|---|---|
version | string | Current format version. Use "2.0". |
displayNames | object | Optional map from GitLab username to local display name. |
groups | array | One entry per distributed repository. |
groups[].uuid | string | Stable identifier used in naming and state files. |
groups[].members | array of strings | GitLab usernames that should receive access to that repository. |
groups[].unassignedMembers | array of strings | Optional members that were known locally but could not be assigned. |
groups[].label | string | Optional human-readable group label. Used by repository name templates such as {{label}} and {{slug}}. |
groups[].metadata | object | Optional group-level string metadata. Used by repository name templates such as {{metadata "fruit"}} or {{.Metadata.fruit}}. |
Import Input
Interactive input, text files, and stdin use one repository group per non-empty row. A row with one value creates a one-person group:
tom
ada
john
ben
A row with comma-separated values creates one group with several members:
alice,bob
john,ada
CSV, TSV, and Excel files may use a header row. Headers named username,
member, members, user, login, or provider_username are treated as
GitLab username columns. Numbered forms such as member1, member2,
username1, or username2 allow several members in one row.
A metadata-only first row such as fruits is not enough to trigger header
mode; include at least one recognized member column such as username,
member, or email.
email is a fallback member column only when no username/member column exists.
If a table contains both email and username, Divekit uses username as the
GitLab username and imports email as metadata.
Any non-empty column that is not selected as a member, UUID, or label column is
stored under groups[].metadata using a normalized lowercase key. For example,
header Favorite Fruit becomes favorite_fruit. A header such as fruits
becomes groups[].metadata.fruits.
Columns named label, group, group_label, repository,
repository_label, repo, repo_label, or title are stored as
groups[].label instead of metadata. Rows with the same uuid or the same
label are merged into one group.
Behavior
- One
groups[]entry results in one logical repository pair per UUID. - If the evaluation pipeline is enabled, the same UUID is used across
workandeval. groups[].labelandgroups[].metadataare optional naming and display fields. They do not replaceuuid; remotes, individuals, and linked targets still join onuuid.members.permissionsfromconfig.jsondefines the default permission level for all listed members.- GitLab operations use
groups[].members;displayNamesonly affects local display output. - Repository name templates can use group labels and metadata through
{{label}},{{slug}},{{metadata "key"}}, and{{.Metadata.key}}. divekit members list,divekit overview, and the GUI show aliased members asdisplay name (@gitlab-username).divekit members alias setreplaces a local member name with the GitLab username in the configured members file and records the display name indisplayNames.divekit members alias unsetremoves only the display-name metadata. It leavesgroups[].membersunchanged.divekit members add,members filter, andmembers excludecreate replacement files instead of editing the existing file in place. They keep UUIDs for remaining groups, drop groups whose member list becomes empty, and ask for confirmation before applying the plan.- If work-target remotes already exist, removing members also revokes matching GitLab project memberships. It does not delete already created repositories.
divekit distributealso reconciles configured member changes on existing work projects when changes are applied through its interactive configured-members edit flow: current members are assigned, and previously configured members that moved away from a UUID are removed from that UUID’s work project.- Manual edits to
members.jsondo not give Divekit the previous member set needed for removal planning. Use the interactivedistributeedit flow,divekit members exclude, ordivekit members filterwhen remote memberships should be revoked automatically.
Path Resolution
Divekit resolves members.path in this order:
- Absolute path: used directly.
./or../: resolved relative to the current working directory.$DIVEKIT_MEMBERS/...: resolved under the configured members base directory.- Any other relative path: resolved under the members base directory.
If DIVEKIT_MEMBERS is not set, the default base directory is ~/.divekit/members.
Related pages: