# Teams

> Share whole conversations from selected repositories with teammates through storage your team controls.

A Team shares conversations from chosen repositories through a bucket or
shared folder your team controls. Every member uploads matching conversations
under the same signed policy and receives the others' conversations read-only,
labeled with the person and device they came from.

- App: **Teams**
- CLI: `hansard team`

## What a Team shares

A Team policy lists folders, repositories, and repository owners. A
conversation that matches any entry uploads whole. A folder matches
conversations started in it or inside it. A folder in your home folder is saved
as a path from the home folder, such as `~/work/api`, so it matches the same
folder on each member's computer. Hansard never splits a conversation or picks
individual messages.

| Uploads                                                          | Stays on the device          |
| ---------------------------------------------------------------- | ---------------------------- |
| Full transcripts, including every tool call and its output       | Original harness files       |
| Conversation metadata, with structural local-path fields removed | Memories                     |
| Attachments and captured artifacts, as files                     | Deep Recall research threads |

Hansard removes structural local-path fields and metadata values that consist
only of an absolute local path. Transcript metadata and event strings shorten
a path only when that record also holds it as a separate non-tool, non-text
value. Paths embedded
only in titles, summaries, or other strings can remain, including Markdown
titles. Conversation frontmatter clears the working-directory fields. Message
text, tool calls and results, attachments, and artifacts remain unchanged and
can contain local paths or material outside the policy.

Each computer uploads a conversation again only after it changes, and checks
its own copies in a Team bucket once a day. It also checks a file again when
another installed copy changes its local upload record. A conversation that
stops matching the policy stays in the Team's storage as it was last uploaded.
Conversation views stay on each computer, since every member builds them from
the transcript.

Each upload leaves a small change mark in the Team's storage, and the other
members receive it within seconds of seeing that mark move. Uploads from a
member on an earlier release leave no mark, so they arrive at the Team's
receive interval. Update every member to receive changes this fast.

A manager can turn on **Compress shared files** on the Team's **Rules** page.
Uploads then store text files from 1 KiB to below 5 MiB as gzip when that saves
at least a tenth, and every member still receives plain files. Once it is on, it
stays on. Members on an earlier release stop syncing the Team until they
update, so the **Rules** page shows how many devices are ready before you turn
it on.

## Create or join in the app

> **Matching conversations upload in full:** Anyone with read access to the Team's bucket or folder can read every
> uploaded conversation, including tool output and attachments. Redaction
> replaces known secret patterns only. Open a few matching conversations and
> review them before you connect.

To join a Team:

1. Get a Team invite from one of the Team's managers. The invite contains no
   credentials. For a Team in Google Drive, Dropbox, OneDrive, or iCloud
   Drive, ask the manager to share the Team's folder with you in that app. For
   a bucket, get your own access key through a separate secure channel.

2. Open **Teams** in the dock and select **Join a team**.

3. Paste the invite. For a synced folder, choose your copy of the Team's
   folder. For a bucket, enter the **Access key ID** and **Secret access
   key**. Select **Look up team**. Hansard reads the Team's details and saves
   nothing yet.

4. Review the Team: its managers and members, its storage, what it shares,
   what teammates will see, who can change the rules, and its extras. Select
   **Continue**.

5. Under **You upload**, choose **Everything** the Team's rules match, or
   **Folders I pick**. The second choice narrows the Team's rules for this
   computer and can never widen them. Select the acknowledgment, then select
   **Join** followed by the Team's name.

To create a Team:

1. Open **Teams** in the dock and select **Create a team**.

2. Enter a **Team name**. A picture and a description are optional.

3. Choose the storage. **Google Drive**, **Dropbox**, **OneDrive**, and
   **iCloud Drive** keep the Team in a folder that the provider's desktop app
   syncs, which you then share from that app. **More storage options** holds
   Cloudflare R2, Amazon S3, other S3-compatible buckets, and any folder.

4. Under **What should the team share?**, keep **Shares** set to
   **These projects** and select **Add a project** for each repository owner,
   repository, or folder.
   A folder rule shares conversations started in that folder or inside it.
   **Every conversation** shares every archived coding conversation. Set
   **Upload**: **As changes are ready** uploads as soon as the archive
   changes, at most once every 2 minutes. **Allow memory sharing** and
   **Allow agent messages** start off, and each member still chooses for
   themselves.

5. Review the summary, select the acknowledgment, then select **Create team**.

6. Select **Copy invite** and send the invite to teammates separately from
   their storage access.

The **Teams** view lists your Teams in the sidebar. Each Team expands to its
**Conversations**, **Members**, and **Rules**, then one row for each member.
A Team's page has four tabs:

- **Conversations** lists what teammates shared and the conversations on this
  computer that the Team receives under its rules and your folder choice,
  newest first, each tagged with whose it is. Select a member, or **You**, to
  see only their conversations.
- **Members** shows each person with their picture and role. Managers invite
  people from here.
- **Rules** describes the rules in plain words, who can change them, and
  every change with who made it and when.
- **Your sharing** holds this computer's folder scope, the extras,
  **Project boards**, **What teammates see of your sessions**,
  **Connections to teammates**, the sync direction, the storage connection,
  how teammates see you, and the button to leave the Team.

Teammates see your name and picture. Set the picture under **Your picture** in
**Settings → General**, or select **Change** under **How teammates see you**
on the **Your sharing** tab.

Team conversations stay out of Sessions, Stats, and Graph. To show them there,
turn on **Show team conversations in Sessions, Stats, and Graph** in
**Settings → General**, use the **Teams** toggle in the Sessions filters, or
run `hansard config set privacy.teamConversations shown`. `hansard history`
follows the same setting; `--team-sessions include` brings team conversations
into one list or search, `--team <team-id>` lists one Team's, and
`hansard stats --team <team-id>` scopes Stats to one Team.

When a manager changes the rules to share more, your uploads keep following
the rules you accepted until you review the change on the **Rules** tab and
accept it there. A change that shares less applies at once.

## Create and join from the CLI

1. Create the Team with its repositories and owners:

   ```sh
   hansard team create \
     --name "Example Team" \
     --target r2 \
     --endpoint https://ACCOUNT_ID.r2.cloudflarestorage.com \
     --bucket example-hansard-team \
     --repos github.com/example/app \
     --owners example
   ```

   A shared folder works too: pass `--endpoint file:///home/user/hansard-team`
   instead of the cloud options. Hansard previews how many conversations match,
   then signs the policy and uploads after you confirm. In a script, add
   `--yes`.

2. Print an invite for teammates:

   ```sh
   hansard team invite example-team
   ```

3. On a teammate's device, preview the Team first. Preview shows its rules,
   managers, and storage, and how many local conversations the rules match,
   and saves nothing:

   ```sh
   hansard team preview --invite 'hansard-team-invite-v1.…'
   ```

4. Join with the invite and that device's own credentials:

   ```sh
   hansard team join --invite 'hansard-team-invite-v1.…'
   ```

   Join verifies the invite and the signed policy, previews what this device
   would upload, and saves the connection after you confirm. Run `hansard sync`
   to start exchanging conversations.

5. Check the Team:

   ```sh
   hansard team status
   hansard sync status
   ```

After you join, these commands change what you share:

```sh
hansard team rules example-team
hansard team accept example-team --policy-hash <hash>
hansard team scope example-team --folder ~/work/api
hansard team sharing example-team --memories off --agent-messages on
```

- `rules` shows the current rules, the ones you accepted, and any change that
  waits for you. `accept` takes the policy hash `rules` shows, and works only
  in an interactive terminal outside an agent session, or on the **Rules** tab.
- `scope` limits your uploads to conversations started inside the folders you
  name, and `--all` removes the limit. The Team's rules still apply.
- `sharing` records your memory sharing and agent message choices for the
  Team. Both start off, and each takes effect only while the Team allows it.

## Share a project board

Project boards are personal until you turn sharing on. Open a project in
**Boards**, then select **Personal board** beside **Follow this board** to open
**Board sharing**. Turn on **Share this board with Example Team** and select
**Save**. On a shared board, the same button reads **Shared with** followed by
the Team's name.
The team's rules and your folder choice must include that project, and a
manager must allow **Agent messages**.

New threads and posts then go to the shared board. **Also share the N earlier
threads** starts off and shows the number of private threads. Select it only
to share those threads and their replies. Open **Board sharing** again to
share earlier threads later. A project can share with one team at a time.

The shared board appears under **Teams** in the Boards sidebar. People and
agents working in that project use it. Posts from another member's agent are
notes that cannot start or steer work. Each device signs its board records.

The same controls appear under **Teams > Your sharing > Project boards**.
Turning a project's switch off stops new publication and reception. A storage
request already sent can finish. Received posts stay readable, and new posts
return to the personal board. The **Agent messages** switch stops every shared
board for that team. Enabling one project afterward restarts only that project.

Use the CLI to read or change a project's choice:

```sh
hansard boards sharing <board-id>
hansard boards sharing <board-id> --team example-team --enabled on
hansard boards sharing <board-id> --team example-team --enabled on --share-earlier
hansard boards sharing <board-id> --team example-team --enabled off
```

Find board IDs with `hansard boards list --category project`. Each computer
keeps its own choices. Agents cannot change them. No reimport is required.

## Let agents message teammates

Teammates' agents can message your agents over a direct connection between
your computers. Each computer needs the Hansard desktop app for macOS, which
runs the connection in the background. Shared boards need none of this: they
travel through the Team's storage.

1. A manager allows agent messages for the Team: **Allow agent messages**
   when creating it, or **Agent messages** on its **Rules** tab later.

2. A manager names a relay that the Team runs itself. Hansard does not ship a
   relay, and without one teammates do not connect:

   ```sh
   hansard team network example-team --relay https://relay.example.com
   ```

   Each member accepts a new relay on **Your sharing** under
   **Connections to teammates**, or with
   `hansard team network example-team --accept`. For a relay that admits only
   listed devices, `hansard team relay-allowlist example-team` prints their
   endpoint IDs.

3. Each member turns on **Agent messages** under **Extras** on
   **Your sharing**, or runs:

   ```sh
   hansard team sharing example-team --agent-messages on
   ```

4. On **Members**, a manager admits each device under
   **Devices for agent messages** after its owner reads out the same key
   fingerprint from their own **Members** tab. The CLI equivalent is
   `hansard team devices example-team --admit <key-id>`.

Teammates then see each other's live sessions in projects whose boards they
share: the agent, the project, the git branch, and whether it is busy, never a
folder or a conversation. `hansard team presence` shows and changes what this
computer sends. Messages from teammates' agents wait under
**From other people** in **Boards → Direct messages**.

How a teammate's request reaches your sessions is your choice for each person,
set from the **Requests** button on their **Members** row or with
`hansard team requests`. **Ask every time** is the default: nothing starts
until you approve the request in Hansard, on a paired phone, or in the Slack
bot's direct message. **Ask for sessions that skip permission prompts** and
**Trust** start some or all requests at once. `hansard team status` shows how
many teammate devices this computer reaches, or why it reaches none.

## Keep redundant storage copies

Each Team connection can maintain up to 16 additional copies in empty shared
folders or S3-compatible bucket prefixes. On the Team's **Your sharing** tab,
select **Add a copy** under **Storage**.
Each copy keeps the signed Team identity and every member's existing shared
uploads, including signed board heads and posts. It does not include unrelated
Personal Sync data.

```sh
hansard team storage add --target example-team --type folder --folder /path/to/team-copy --name "Team backup" --yes
hansard team storage list --target example-team
hansard team storage sync --target example-team
```

Use `--type r2|s3|custom` and the destination's storage settings for a bucket.
Each copy uses its own credentials. Google Drive, OneDrive, and Dropbox copies
are available for Personal Sync revision backups only.

Manual sync updates all copies. Scheduled sync attempts each copy at most
once every 30 minutes while the configuring computer is running. **Copy now**
updates them immediately. Each copy reports its own last success and error,
and one failure does not stop the others. The primary must be reachable to
update copies. Hansard does not automatically move writes during an outage.

A manager can create a connection invite for a completed copy from its row
in Settings or with:

```sh
hansard team invite example-team --storage-copy <copy-id>
```

The invite reads the copy's signed manifest and works while the primary is
unavailable. A recovery installation joins with that invite and the copy's
storage credentials. An interrupted transfer of mutable Team files can leave
a partially updated destination. Hansard marks that copy incomplete and
withholds connection invites until an update completes.

Disconnecting a copy stops updates without deleting its remote data.
`hansard team storage remove <copy-id> --target example-team` does the same.
Objects removed from the primary remain in copies. A Team destination that
still contains legacy raw or memory files must be cleaned before copying.

## How the Team policy is protected

- Creating a Team makes a manager key on the creator's device and signs the
  policy with it. Only a device holding that key can change the policy.
- An invite pins the Team, its current policy version, the manager's key
  fingerprint, and the storage location. After you change the policy, print a
  new invite.
- Bucket access alone cannot join a Team or change its policy. Hansard rejects
  a policy that is unsigned, tampered with, or older than the one it already
  accepted.
- Each device records exactly what it agreed to upload. If the storage
  location or account changes, scheduled uploads pause until you review and
  confirm the new preview by running `hansard sync` in a terminal. A rule
  change that shares more waits for your acceptance on the **Rules** tab.
- Each member's record carries a revision and the device keys that member
  removed. Members on earlier releases cannot read these records and keep the
  details they last verified, so update every member.

## Retire an older Team destination

Always create a Team in a new bucket or prefix. An older destination can hold
personal or out-of-scope conversations, original harness files, snapshots, and
old object versions from earlier Hansard releases.

To remove original harness files that older releases uploaded, preview the
cleanup first:

```sh
hansard team purge-legacy-raw example-team --dry-run
hansard team purge-legacy-raw example-team --yes
```

The cleanup removes only the original-file copies it can identify, both in the
bucket and in this device's received Team copies. It does not remove
conversations, snapshots, or bucket versions. Retire the old destination with
your storage provider's controls.

To back up your own complete archive across your devices, use
[Personal Sync](https://www.hansard.dev/sync/personal-sync/).
