> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xysq.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tags

> A controlled vocabulary for your sources — define tags once, attach them to any captured content, and (soon) scope recall to exactly the sources that carry them.

Tags are one vocabulary per user, spanning all your vaults. You define them
deliberately (no free-form drift), attach them to captured sources at any
time, and rename or delete them with every application following instantly.

```python theme={"dark"}
from xysq import Xysq

with Xysq() as client:
    tags = client.tags.list()              # seeded on first read
    print([t.name for t in tags])          # ['confidential', 'finance', ...]

    client.tags.create("deploy")
    out = client.tags.apply(vault_id, source_id, add=["deploy", "infra"])
    print(out.applied)                     # ['deploy']
    print(out.unknown)                     # ['infra'] -- not created, echoed
```

Two rules do most of the work:

* **The vocabulary is curated.** Unknown names on `apply` are echoed back in
  `unknown`, never auto-created, and the call never fails over them. Create
  a tag first if you meant it.
* **Tags are yours.** On shared vaults, each user sees and manages only
  their own tags — a teammate's labels never leak into your view.

## API

### `client.tags.list() -> list[Tag]`

Your vocabulary with live `applied` counts. The server seeds a small
starter set (`work`, `health`, `personal`, `finance`, `tech`, `pii`,
`confidential`) on first use; every seed is yours to rename or delete.

### `client.tags.create(name) -> Tag`

Names are slugs: 1-30 chars of `a-z`, `0-9`, `-`, starting alphanumeric.
The server lowercases and trims for you. `409` if the name exists.

### `client.tags.rename(tag_id, name) -> Tag`

Every existing application follows the rename instantly. `409` if the new
name is taken.

### `client.tags.delete(tag_id) -> int`

Detaches the tag everywhere; returns how many sources carried it.

### `client.tags.apply(vault_id, source_id, add=[...], remove=[...]) -> SourceTagsResult`

Attach/detach by name on one captured source. Reader access to the vault
suffices (tagging organizes your view; it changes nothing shared). The
result carries `applied`, `removed`, `unknown`, and the source's resulting
`tags`.

## What's next

Tag-scoped recall — `pull` restricted to sources carrying a tag (and to a
single thread or session) — ships with the server's scoped-retrieval wave.
The vocabulary you build now is the one those filters will use.
