# Using One Track as an Agent

> The web app at [/app](https://one-track.app/app) is a WASM SPA built for humans; agents get the same tracks, entries, and dependency graph through the `one_track` CLI.

## Install

POSIX (macOS, Linux):

```sh
curl -fsSL https://one-track.app/install.sh | sh
```

Windows (PowerShell):

```powershell
irm https://one-track.app/install.ps1 | iex
```

Full install page: [one-track.app/cli?format=md](https://one-track.app/cli?format=md).

## Authenticate

Device authorization plus end-to-end-encryption unlock, in one step:

```sh
one_track login
```

What happens, from your side:

1. The CLI prints a verification code and a link of the form `https://one-track.app/activate?code=…`, then polls in the foreground.
2. A signed-in human opens that link in a browser, checks the code and device name, and approves — choosing a role and expiry for the grant. Relay the code and URL to your human; the request expires after 15 minutes.
3. On approval the CLI receives an `ot_live_…` token (delivered exactly once) and saves it locally.
4. The CLI then unlocks the account's end-to-end-encrypted data: it prompts for the encryption passphrase, or reads it non-interactively from `--passphrase-file FILE` or `$ONE_TRACK_PASSPHRASE`. On a brand-new account this step sets the passphrase instead. Once unlocked, data commands read and write the same encrypted document the web app shows.

Options: `--device-name NAME` (or `$ONE_TRACK_DEVICE_NAME`) labels the request on the approval page; `--url` (or `$ONE_TRACK_URL`) targets a non-default server.

Alternative sign-in with an emailed one-time code (no browser approval needed, and required later for `github link`):

```sh
one_track login you@example.com
one_track login you@example.com --code 123456
```

`--token TOKEN` (or `$ONE_TRACK_TOKEN`) authenticates the account and organization commands with a pre-issued token. It cannot run data commands: your tracks are end-to-end encrypted, and a bare token carries no key. Data commands need a `login` that entered the passphrase on this device.

Session management:

```sh
one_track whoami
one_track logout
```

Every command accepts the global `--json` flag for machine-readable output and `--yes` to apply one-way-door changes without the interactive confirmation.

## Connect over MCP

`one_track mcp` serves the Model Context Protocol over stdio. Register it with your agent runtime (for Claude Code: `claude mcp add --scope user one-track -- one_track mcp`) after `one_track login`; by default it exposes only the read tools — `list`, `show_entry`, `list_tracks`, `whoami`, and `account`. Pass `--profile write` to also expose `add_entry`, `complete_entry`, `reopen_entry`, `edit_entry`, `remove_entry`, `link_entries`, `unlink_entries`, `add_track`, `edit_track`, and `remove_track` — against the same state the CLI and web app use. Tool selectors accept a UUID, a UUID prefix, or the exact title. Sign-in and account administration (sharing, visibility, org, billing) stay on the CLI. Invoking `one_track` directly with `--json` remains fully supported.

## Manage tasks

Entries (tasks) belong to tracks (projects) and form a directed acyclic dependency graph. Anywhere a command takes a track or entry, you may pass a UUID, a UUID prefix, or the title.

Tracks:

```sh
one_track track list
one_track track add "Launch prep" --description "Everything before the announcement"
one_track track edit "Launch prep" --title "Launch"
one_track track rm "Launch" --force
```

`track rm` refuses to delete a track that still has entries unless you pass `--force` (which deletes them too).

Read the dashboard and individual entries:

```sh
one_track list
one_track list --track "Launch" --active
one_track list --completed
one_track show "write announcement"
```

`show` prints one entry in full, including its dependencies.

Create entries, optionally wired into the dependency graph at birth:

```sh
one_track add "write announcement" --track "Launch"
one_track add "publish announcement" --description "after review" --parent "write announcement"
one_track add "draft outline" --child "write announcement"
```

`--parent` names an entry this one depends on; `--child` names an entry that depends on this one. Both are repeatable. Without `--track`, the entry lands in the active track.

Complete, reopen, edit, delete:

```sh
one_track done "write announcement"
one_track reopen "write announcement"
one_track edit "write announcement" --title "write launch post" --description "800 words" --track "Launch"
one_track rm "draft outline"
```

Rewire dependencies after the fact — `link PARENT CHILD` makes CHILD depend on PARENT:

```sh
one_track link "write announcement" "publish announcement"
one_track unlink "write announcement" "publish announcement"
```

## Share and publish

Sharing and visibility commands take UUIDs (get them from `one_track list --json` or `one_track org show`). Sharing rides on Pro; the plan itself is CLI-manageable:

```sh
one_track account
one_track upgrade
one_track downgrade
```

Share a single track with another account by email (`--level view` is the default). The track stays end-to-end encrypted: the CLI puts it in an encrypted share doc and seals that doc's key to the recipient once they have accepted and set their own passphrase. Your next data command after they accept completes the hand-over; until then their side shows the track as waiting.

```sh
one_track share invite TRACK_UUID them@example.com --level edit
one_track share list TRACK_UUID
one_track share set-level TRACK_UUID SHARE_UUID view
one_track share revoke TRACK_UUID SHARE_UUID
one_track share accept INVITE_TOKEN
one_track share enable TRACK_UUID
```

`share enable` is only needed for a track that was shared before encrypted sharing existed: it creates the share doc so the existing audience can read the track again.

The invite lands in the recipient's email; they accept with `share accept` or in the web app.

Track visibility inside an organization (`private`, `by_role`, `org`, or `public`, bounded by your role's grants):

```sh
one_track visibility get TRACK_UUID
one_track visibility set TRACK_UUID org --org ORG_UUID
one_track visibility set TRACK_UUID by_role --org ORG_UUID --roles ROLE_UUID,ROLE_UUID
```

Organization administration:

```sh
one_track org create "Acme"
one_track org list
one_track org show ORG_UUID
one_track org member add ORG_UUID them@example.com --role ROLE_UUID
one_track org member set-role ORG_UUID USER_UUID ROLE_UUID
one_track org member remove ORG_UUID USER_UUID
one_track org role create ORG_UUID "Reviewer"
one_track org role edit ORG_UUID ROLE_UUID --grant org=yes,private=no,by_role=no,public=no --caps assign_roles=yes,edit_shared_tracks=no
one_track org role delete ORG_UUID ROLE_UUID
one_track org audit ORG_UUID
one_track org risks ORG_UUID
one_track org cli ORG_UUID off
```

Destructive or hard-to-reverse changes (the "one-way door") prompt for confirmation; pass `--yes` to acknowledge non-interactively.

Still needs a human in the web app:

- Approving a device-authorization request, choosing its role and expiry: [one-track.app/activate](https://one-track.app/activate).
- Passkeys, recovery codes, and changing the encryption passphrase: managed in the web app at [one-track.app/app](https://one-track.app/app).

## GitHub integration

Links a One Track entry to a GitHub issue so that `github sync` mirrors the issue's state onto the entry: closing the issue completes the entry, reopening it reopens the entry. The sync runs on your machine against the GitHub API, using your own `GITHUB_TOKEN`; the server never learns which repository, issue, or entry is linked.

```sh
export GITHUB_TOKEN=...
one_track github link "ship docs" owner/name#203
one_track github status
one_track github sync
one_track github unlink "ship docs"
one_track github migrate-links
```

`github link` takes an entry (UUID, UUID prefix, or title) and an issue as `owner/name#number`. `github status` lists each linked issue with the last applied state; `github migrate-links` converts links made with the earlier webhook integration, which no longer fires. The web app shows an entry's linked issues read-only, together with the commands to run.

If you used the earlier webhook integration, withdraw its agent access after upgrading: `one_track agent grants list` and `one_track agent grants revoke GRANT_ID` (also removes the agent from your roster when it has no other grant), and `one_track agent triggers list` / `revoke FINGERPRINT`. Revoking withdraws future access, not what the agent already read: treat anything it could read before as exposed, and rotate any credentials that data contained.

## More

- [one-track.app/llms.txt](https://one-track.app/llms.txt)
- [one-track.app/security?format=md](https://one-track.app/security?format=md)
- [one-track.app/pricing?format=md](https://one-track.app/pricing?format=md)
