# Synchain — instructions for AI agents

Synchain is an all-in-one platform for music and audio production collaboration: a
real-time hi-fi Creative Space, VST3 direct connect from your DAW, and project files,
calendar, discussion and members — from the browser, or from your terminal with the
Synchain CLI.

This page is the machine-facing runbook for https://www.synchain.ca. If you only need to know what
the product is and which pages exist, read [/llms.txt](https://www.synchain.ca/llms.txt) instead.

## Install the CLI

```bash
npm i -g @synchain/cli     # global `synchain` binary, Node.js >= 20
npx @synchain/cli --help   # or run it without installing
```

Package: <https://www.npmjs.com/package/@synchain/cli>

## Authenticate

1. A human generates a CLI access key in the web app under **Settings → CLI Access**.
   Keys look like `synch_live_sk_<48 hex>` and are shown **once**.
2. Pass the key through the environment — never as a command-line flag. Argv ends up in
   shell history and `/proc/<pid>/cmdline`, which leaks the bearer:

```bash
export SYNCHAIN_TOKEN=synch_live_sk_…
synchain login --base-url https://www.synchain.ca
```

`login` validates the key against `GET /api/user/me` and stores it in the OS config
directory (`%APPDATA%\synchain\config.json` on Windows, `~/.config/synchain/config.json`
mode `0600` on POSIX). In ephemeral CI, keep `SYNCHAIN_TOKEN` set and re-run `login`
each job.

The same key works directly against the HTTP API:

```
Authorization: Bearer synch_live_sk_…
```

## What you can do

Pick a project first (`synchain project use <id-or-prefix>`), then:

- **Files** — list, upload, download, move, rename and remove project files and folders.
- **Calendar** — list, add, edit and remove project events.
- **Discussion** — list threads, read a thread, post a thread, reply.
- **Members** — read-only listing of a project's members, permissions and roles.

Every read command supports `--json` and prints the raw API payload to **stdout**;
progress and errors go to **stderr**. `--format json` is accepted globally and means the
same thing.

### One argv pitfall that will bite a generated command line

Pass any option **value** that begins with `-` using `--opt=value`, never `--opt value`:

```bash
synchain discussion post --title=-h --content=x --json    # correct
synchain discussion post --title -h --content x --json    # WRONG — see below
```

The CLI has to decide whether you asked for help *before* it can parse the command line
(the arg parser prints text help and exits the moment it sees `-h`/`--help`, which would
defeat `--help --format json`). So it scans the raw argv, and a bare `-h` sitting there as
a *value* is indistinguishable from a request for help. The failure mode is quiet: the CLI
prints the command tree and **your write never happens**, with exit code `0`. The
`--opt=value` form is not affected.

### Preview a write before you make it

Every **mutating** command takes `--dry-run`: it validates arguments, resolves the id,
prints the plan, and stops before the write. Exit code stays `0` — a rehearsal that
completes is a success.

```bash
synchain files rm a1b2c3d4 --dry-run --json
```

Use it. Ids accept an **8-char prefix** that the CLI resolves for you, and a prefix that
matches the wrong object is the one mistake that silently destroys someone else's work.
Resolving a prefix needs a lookup, and that lookup still runs under `--dry-run` — so a
dry run that succeeds **on a prefix** also proves the target exists and you may touch it.
A full UUID skips the lookup (the real run skips it too), so there it only echoes your
input back.

## Rules you must follow

- **Attribution is automatic and cannot be disabled.** Every discussion post or reply
  made through a CLI key is flagged `is_ai_generated = true` server-side and rendered
  with an AI badge in the web UI. Do not attempt to work around it.
- **Scopes are the AND of account scopes and project scopes.** A `403 scope_denied` or
  `403 project_scope_denied` means a human has to widen the grant — retrying will not
  help. The `members` scope is off by default.
- **Write access needs member-or-admin permission.** A viewer is read-only.
- **Exit code `1` means any error**, `0` means success (including a completed
  `--dry-run`). In text mode the message on stderr is prose; in JSON mode **every stderr
  line is itself JSON**, so parse stderr line by line and never regex prose. Errors:

```json
{ "error": { "code": "forbidden", "status": 403, "url": "https://…", "detail": "…" } }
```

  `code` is the server's own `snake_case` code passed through verbatim, falling back to
  `http_<status>` when the response body carries none, and `client_error` with
  `"status": 0` when the request never reached the server. The only other line the CLI
  can emit is an advisory — an orphaned storage key after a failed `files upload`:

```json
{ "warning": { "code": "orphaned_upload_key", "storageKey": "…", "detail": "…" } }
```

## Do not crawl these paths

None of them is content: they are the authenticated app surface, the HTTP API and the
login view. Without a session they answer with a redirect to the login page or a `401`,
so whatever you index from them describes the login wall, not Synchain. Use the CLI or
the API with a key instead. The same list is served in
[/robots.txt](https://www.synchain.ca/robots.txt) as `Disallow` rules:

- `/dashboard`
- `/projects`
- `/settings`
- `/admin`
- `/api`
- `/auth`

Everything else on https://www.synchain.ca is public marketing content and is explicitly open to AI
training crawlers, AI search indexers and user-triggered fetchers — see
[/robots.txt](https://www.synchain.ca/robots.txt) for the per-user-agent policy and
[/sitemap.xml](https://www.synchain.ca/sitemap.xml) for the full URL list with hreflang alternates.

## Read those pages as Markdown, not HTML

Every marketing page is served in a Markdown form as well. **Append `.md` to its URL**:

```bash
curl https://www.synchain.ca/features.md      # English
curl https://www.synchain.ca/zh/faq.md        # Chinese
curl -H "Accept: text/markdown" https://www.synchain.ca/features   # same document
```

The three home pages have no path segment to suffix, so they are `/index.md` (English),
`/zh.md` and `/fr.md`. Every other page is `<page-url>.md`, in all three languages.

Both forms return `Content-Type: text/markdown; charset=utf-8` and open with YAML
frontmatter — `title`, `description`, `url`, `canonical_url`, `language` and
`last_updated` — so you can tell what a page is, which HTML URL is canonical for it and
when it last changed without parsing the body. The body is the same content as the HTML
page with the navigation, footer and decorative markup removed, which is why you should
prefer it: it costs a fraction of the tokens and nothing has to be scraped out of it.

The `Accept: text/markdown` header only switches the response when it outranks
`text/html`, so an ordinary browser request is never affected. If you would rather not
depend on header negotiation, use the `.md` URL — it is unambiguous.

## Full documentation

- [CLI command reference on npm](https://www.npmjs.com/package/@synchain/cli) — the package page renders the
  full command reference shipped with every release, so it always matches the version you
  just installed.
- `synchain --help` — same reference offline. `synchain --help --format json` prints the
  whole command tree as JSON, which is the cheapest way for an agent to discover every
  command, flag and subcommand without parsing prose.
