Skip to main content
Nineteen commands. Each states what it does and what it deliberately does not — the boundary is the part that would otherwise be guessed. Four rules hold throughout. Nothing reaches a colleague’s machine unless their configuration asks for it. A store moves the skill’s one label, latest; a colleague receives the version because their file follows latest — the default — and keeps the version they pinned otherwise. The platform pushes nothing. Nothing writes to a directory it did not create unless --force is given — and that covers anything already on the machine, not only skills you wrote yourself. Every command accepts --help and prints its own usage, flags and conflicts, as text. Long options take two dashes. A single dash is only ever a single-letter short option, and the only two are -h for --help and -v for --version. -location is refused rather than accepted as a synonym, so the documented spelling and the working spelling cannot drift apart. Nothing edits a preference. Disabling a skill and holding a version are lines in a configuration file — you edit it, and sync applies it.

to11

The root command. With no arguments it does the job the CLI exists for: skills on disk, current. Does — in a location that is not linked yet, link it — signing you in first when nobody is — then take in the skills already in its targets, and then run to11 skill sync for it. In a linked location, run to11 skill sync under a one-line header, to11 CLI <version> on stderr, and ask nothing; stdout is the sync’s. After a sync that changed nothing, add one line to stderr: `to11 --help` lists the commands. Does not — print the command list, which is to11 --help; take a project or target from a flag — it reads them from TO11_ORGANIZATION, TO11_PROJECT and TO11_PROJECT_ID, and to11 link takes them as flags; guess a subcommand from a near-miss. Conflicts — --non-interactive with --interactive. The first run in a repository, signed in, with one organization and a folder named like a project:
A sync that changes nothing prints nothing here, so the Next: line follows the link’s own lines. Every later run in that directory is the sync:
The `to11 --help` line is never printed by to11 skill sync, nor under --format json. Without a terminal, or with an agent detected, the questions are not asked. A value the link still needs is answered with one action_required object on stdout, exit 1, and nothing is written. With nobody signed in the answer is not_signed_in, in a linked location as well as an unlinked one, and nothing is synced. An unknown subcommand prints the command list to stderr and exits non-zero. Settles which project a location receives skills from, into which targets, and writes that location’s skills.yaml. Does — sign you in when nobody is; take each value from a flag, a variable, the file already there, or a default it can derive, and ask only for what is left; write <repo root>/.to11/skills.yaml inside a git repository, or ~/.to11/skills.yaml outside one or with --global; take in the skills already in the location’s targets; offer the to11 plugin for the agents on your PATH that lack it; name the project in the location’s sessions.yaml when that file names none, so Claude Code sessions go to the project the skills come from; ask once whether to sync those sessions automatically, and in a repository send the ones already there on a Yes. Does not — sync — a bare to11 links and then syncs; create an organization or a project; ask for a prefix; remove a project, a standard target or a per-skill statement the file already holds. Conflicts — --non-interactive with --interactive; --new-skills with --no-new-skills; --auto-sync with --no-auto-sync.

What it decides

A value is asked for only when every source above it is empty, and only at a terminal. Without one, the question is an action_required answer instead. The directory-name match compares the repository root’s folder name, ignoring case, with the project part of each workspace/project you can read. One match is offered as a yes-or-no question; with none or several, Which project? lists every project with the matches first. It applies to a repository only, never to your home. --yes accepts a single match; it never chooses between several. A file that already names projects is read as answers. With exactly one project, that project is taken without asking. With several, Which project? offers the file’s first entry as the default. The write adds the chosen project and keeps every other entry in the file — in a committed repository file, the entries a teammate added stay. A location belongs to one organization. --organization or TO11_ORGANIZATION naming an organization other than the one the file names is refused before anything is asked. A value you cannot read is asked again. A project or organization given by flag or variable that you cannot read is said in one line, and the question follows; without a terminal, the same sentence leads the action_required message, and choices holds the values you can read. --yes answers confirmations, never data questions. It accepts a single directory-name match, the detected targets, and the plugin offer. It never chooses an organization or a project from a list.

The questions

Everything here is on stderr; a link prints nothing on stdout. Each question is drawn in place, and once answered it leaves one ✓ question answer line, with a blank line between questions. The opening names what is set up. Setting up the repository <name>., the repository root’s folder name, for a repository; Setting up your home configuration, which applies in every directory. for your home, because skills linked there reach every directory. At a terminal the to11 wordmark stands beside the two lines. ✓ Signed in as follows, and names your organization only when you belong to one; in several, Which organization? comes next and lists them by slug, each with its display name beside it when that differs. With nobody signed in, the sign-in comes first. The skills come as a statement when the project publishes at least one on latest: All skills are installed, including ones published later:, with the skills’ names under it, at most three and a count of the rest, and two buttons. OK receives every skill and keeps following latest, so a skill stored later arrives too, and answers Install new skills automatically? with Yes. Customize asks Which skills?, then Install new skills automatically?. When the file already turns one of the project’s skills off or selects skills, or --new-skills or --no-new-skills is given, the statement is not made and Which skills? comes straight away, so OK never undoes a choice made before. An entry linked without skills is the exception: a re-link reads it as not written yet, as the new-skills question below says. --skill, --yes and runs without a terminal ask neither. At a terminal, --skill and --yes print one line instead, such as 3 skills: code-review, deploy-checklist and incident-triage, and a project that publishes nothing prints No skills published yet. Which skills? lists them, each checked unless your file disables it, so Enter receives them all:
Typing filters the list by name, ignoring case. space checks or clears the row under the cursor; on Select All it checks every skill, or clears them all when every one is checked. At most 20 rows show at once, with a scrollbar beside them when there are more; on a short terminal fewer rows show, then the description goes. Description shows the highlighted skill’s description, two lines at most. Enter with nothing checked is an answer too, ✓ Which skills? none. A skill another project in your file already names is that project’s to enable or disable; a Not listed row says which. Unchecking a skill writes disabled: true for it under the project in skills.yaml, and checking one again removes that. A skill unchecked in your home file is off in your own directories only; a repository that asks for it still installs it there. To keep it out of repositories too, write enforced: true beside the disabled: true it wrote — that reaches a repository whose file names the same organization and the project the same way (acme/web, not its id). You keep following latest, so a skill stored later still arrives. --skill answers Which skills? without the list, with or without a terminal: the skills named, matched by slug ignoring case, are checked and every other one is unchecked; --skill '*' checks them all. At a terminal a Chosen row names them; a named skill another project in your file already names stays that project’s, and a Not listed row says so, with or without a terminal. A name the project does not have fails the link before anything is written, and the error lists the skills it has. Install new skills automatically? defaults to Yes, with a line under it saying what No means: No keeps exactly the skills selected above. Yes keeps the project entry on latest: a skill stored in the project later arrives, and the skills you unchecked are written disabled: true. No keeps exactly the skills you checked: the project entry gets no label, each checked skill is written { label: latest }, and each unchecked one disabled: true. The line after the write then says ✓ Linked selected skills from <project> @ latest. A re-link of an entry written that way checks the skills it receives and defaults the question to No; answering Yes follows latest again. Only the lines the link writes change: a version pin or enforced stays as written. --yes and runs without a terminal take the default, and keep a selecting entry’s skills as written; --new-skills and --no-new-skills answer it with or without a terminal. When the project publishes nothing yet, or nothing was checked, the line under it says No links <project> without any skills.: No writes an entry that receives nothing, and the line after the write says ✓ Linked <project> without skills. A re-link reads an entry that receives nothing as one not written yet, as it reads an entry whose last pick a prune turned off: it offers to follow latest again, and --yes follows it. Skills the entry turns off stay off. When the list could not be read, the question is not asked and the entry follows latest. Skills are installed for: lists each agent the link writes skills for, with its directory beside it, and the buttons OK and Customize. When no coding agent is on your PATH, No coding agent was found on your PATH. stands under the statement. Customize asks Which agents?, choosing among Claude Code, Codex, and any standard targets the file already holds, which are always kept:
It has no search, Select All or descriptions, and Enter with nothing checked does nothing. --yes asks neither and prints the statement with its rows. ✓ Linked skills from <project> @ latest names the project and latest, and Saved to the file it wrote. The plugin offer, Install the to11 plugin for …?, defaulting to Yes, is made for each of Claude Code and Codex that is on your PATH without the to11 plugin, and ends on ✓ Plugin installed for …. When every agent found already has it, ✓ Plugin already installed for … says so instead. --no-plugin declines it. Without a terminal it is skipped unless --yes was given. The auto-sync question, Sync this repository's Claude Code sessions to to11 automatically?, comes last, defaulting to No, and only when no sessions.yaml already decides it. The answer is written to the location’s sessions.yaml, beside the project the link names there. In a repository that already has Claude Code sessions, the line under the question says Yes also sends the 2 sessions already in this repository. — Yes also sends the 12 newest of the 40 sessions … when they come to more than 512 MB — and a Yes sends them right away, as to11 session sync does, with its Synced … line on stderr; the plugin’s hooks only ever send the session in progress. When the upload fails, The sessions already here were not sent: <reason>. says so, with where it failed and what to do, then `to11 session sync` sends them. The link does not stop there: a bare to11 goes on to the skills sync. --auto-sync and --no-auto-sync answer it without sending anything, and print ✓ Auto-sync on or ✓ Auto-sync off. A sessions.yaml the link cannot read is said on stderr with its error, after Saved to, and the link goes on without writing the project there or asking about auto-sync; a --auto-sync or --no-auto-sync it could not apply is said, as --auto-sync was not applied. The last line after a first link is the next step: using the skills in a new agent session; to11 skill sync after a to11 link, which fetches nothing; `to11 link` picks skills from <project> when you want some. when the link receives no skills; when the project has none yet, <project> publishes no skills yet. `to11 skill store` adds one; whoever follows `latest` receives it.; when nothing was installed because your own skills already use every name, setting prefix: <name> in the file it wrote; and to11 skill list when how many it publishes could not be read, or when nothing arrived for another reason. At a terminal the wordmark, the answers and the ✓ lines are colored; NO_COLOR turns that off, and output that is not a terminal is never colored. The Next: line is printed only after the first link of a location. Re-running to11 link in a linked location ends on the ✓ lines.

Signing in

With nobody signed in, the link’s first step is the sign-in:
Enter opens the browser sign-in, which goes through the dashboard as to11 login --browser does. Ctrl-C, or the end of input, stops with Cancelled.; no browser opens and nothing is stored. A bare to11 in a linked location with nobody signed in asks the same, after Nobody is signed in. Without a terminal there is no sign-in: the answer is action_required with reason: not_signed_in. to11 login signs in without this question.

Ctrl-C

Ctrl-C at a question or a step ends the link with Cancelled. and exits 1. Before the file is written that is all it says, and the file is unchanged: a re-link starts from what it held. After the write, a second line says what is left to do.

Skills already there

After ✓ Linked, every to11 link — and a bare to11 that links — compares the skill folders in the location’s targets that to11 did not deliver with the project, before the plugin offer and the sync. It is to11 skill import run as a step: a folder identical to a published version is adopted without a question, the folders the project does not have are offered for upload with none selected, and a folder that differs from the project’s skill of the same name gets one question. A location with no such folder prints nothing for it. A bare to11 in a linked location never looks.
The lines before the questions count what the step found: the folders adopted as the version the project’s latest points at (already in sync), those adopted as an older version, which the next sync updates (at another version), the folders the project does not have (local skill not in <project>), and what skills.sh installed. A folder that differs is named by its own question. Each answer is carried out when it is given. Without a terminal, a location with such a folder stops after the write and before the sync, with the unmanaged_skills answer on stdout, exit 1; nothing is adopted, uploaded or synced. Each command in its next[] is a to11 skill import line.

What only a person can fix

An account with no organization and an organization with no project you can read cannot be linked by any command. At a terminal each is an error naming what to create and the dashboard address. Without one it is action_required with an ask — see Non-interactive mode.

to11 ui

Setup and an overview of what is set up on this machine or in this repository, full-screen in your terminal. A bare to11 is what sets a location up. On a location that is not set up yet, to11 ui first walks its own onboarding — Skills, then the plugin — which writes what to11 link writes, through the same functions, so a location linked by either is complete to the other. Does — sign you in as a person when nobody is; inside a repository, ask whether to set up the repository or your home; take the organization from the configuration, or from your only membership, or ask; then walk onboarding step by step — Skills, then Code · to11 Plugin. Each step saves as soon as you confirm it. Onboarding ends on All set, which says it is complete; Exit leaves. Later runs open on an overview of what is set up, with anything that no longer holds marked, and an Account row that says who is signed in. While an onboarding step is missing, the overview offers to continue onboarding, walking only the missing steps. Esc leaves onboarding at any step; what was saved stays saved. Does not — work as an API key; run without a terminal; switch the organization of a setup; repair a configuration it cannot read. It takes no flags. It works only as you. Every request it makes carries your signed-in credential, whatever TO11_API_KEY says. The plugin is installed for you, in every project — Claude Code at user scope. It is never written into a repository’s agent settings. Codex has no scope flag, so a Codex install lands where Codex puts it. A setup it cannot use stops the screen. A file that does not parse, an organization you are not a member of, or no organization at all: it says what is wrong, gives a prompt to copy into an AI assistant, prints both on stderr when it closes, and exits 1. Without a terminal it exits 1:

to11 init

to11 init is an alias of to11 link, kept so existing scripts keep working, and is not listed. Its old flags are translated: Like to11 link, it never syncs.

to11 login

Does — sign in as a person and store the credential. When the identity provider offers sign-in with a one-time code, print the code, wait for Enter, and open the page to type it into; otherwise open the dashboard’s sign-in in a browser, which reports back to a listener on this machine. Does not — accept a password typed into the terminal; ask before opening the browser in the browser flow — it is the explicit command; write anything before the sign-in completes — an abandoned or declined sign-in leaves the machine exactly as it was; run without a terminal. Conflicts — --device with --browser (they pick opposite sign-ins); --non-interactive with --interactive. Which sign-in runs. The code flow when the identity provider’s metadata advertises a device authorization endpoint, or with --device. The browser flow otherwise, and with --browser. A provider can advertise the code flow and still refuse it for this client; that refusal falls back to the browser flow without a word, and only with --device is it an error. With a code, any browser on any machine completes it. The code is printed before anything opens, so on a remote machine you can type it into a browser elsewhere; a browser that cannot open here is not a failure:
The code expires at the identity provider, and the CLI stops waiting when it does: the one-time code expired. Denying the sign-in in the browser stops with the sign-in was denied. Either way nothing is stored. Through a browser, it needs a browser on this machine. The command opens one and prints the address as well in case it does not open — but both reach a listener on 127.0.0.1, so the address cannot be carried to another device:
The browser sign-in goes through the dashboard. You sign in, or sign up, on the dashboard’s own sign-in page. An account that is not in an organization yet joins the organizations that invited its verified email, or else goes through the dashboard’s onboarding first. The identity provider may then ask you to approve the to11 CLI, and the browser returns to this machine. The dashboard is TO11_WEB_URL when it is set; otherwise the one the install says it has; otherwise production’s, or staging’s under --dev or TO11_DEV. An install named by --api-url or TO11_API_URL that says nothing, and an identity provider named by --issuer, are opened directly, as before. Without a terminal, it does not wait. It prints the not_signed_in answer on stdout and exits 1, starting no sign-in. A machine where nobody signs in, such as CI, uses an API key in TO11_API_KEY instead. A bare to11 or to11 link with nobody signed in signs in inline, through the browser and the dashboard, after asking first: Press Enter to continue in your browser, or Ctrl-C to cancel. See Signing in.

to11 logout

Does — delete the stored credential and report what was removed. Does not — remove API keys; remove configuration; delete installed skills. After it, commands use TO11_API_KEY when it is set. Logging out leaves skills on disk — logging out is not a request for your agent to stop working.

to11 whoami

Does — print the identity, its organizations, and which credential kind is in use. The answer comes from the platform, so it is a real check rather than a local echo. Does not — modify anything; list skills; fall back to a cached answer when the platform is unreachable — a stale identity answer is worse than none.
With an API key it says so, and never prints the key:

Naming a project

--project takes workspace/project or a proj_ id. An id needs no organization. A workspace/project is looked up in one organization. to11 environment list belongs to no location, and takes the organization from:
  1. --organization <slug>, else TO11_ORGANIZATION
  2. the only organization you belong to
  3. the organization this repository’s skills.yaml and your home one name, when only one names one or both name the same
  4. when they name two different ones: the one that has the project. A project both have, or neither has, needs --organization
  5. with no skills.yaml naming one: the only one of your organizations that has the project. When several have it, the command stops and names them
to11 skill store takes --organization or TO11_ORGANIZATION first, then the organization of the location it acts on. to11 session sync resolves its project as its own section describes.

to11 project list

Lists the projects you can read. Without an organization, the projects of every organization you belong to. It needs a signed-in person. With TO11_API_KEY it stops with listing projects needs a signed-in person.

to11 environment list

Lists a project’s environments. Archived environments are left out.

to11 skill

Does — with no subcommand, print the subcommand list. Does not — sync, list, or contact the platform. Inert by design: a bare parent command that did work would make the most exploratory thing you can type the thing with the most side effects.

to11 skill sync

Reconciles every configured location to what your configuration resolves to. Does — fetch the rendered skills for each target and write them; remove skills configuration no longer resolves; skip and report anything edited on disk; report per skill and per location what changed; leave previous skills in place when a fetch fails, so a broken network still beats nothing. Does not — publish or modify anything upstream; touch a directory it did not create; partially write a skill; prompt for anything but one question — at a terminal, whether to remove a skill you picked that is no longer published (gone) — Remove <slug>, no longer published?, or Remove skills no longer published? for several; skip because a refresh ran recently — an explicit sync always runs. One flag, not several. A directory already there and a skill you edited are one request: install what the configuration asks for, whatever is in the way. Each refusal --force waives exists to stop a sync destroying work nobody agreed to lose, and the flag is that agreement. A directory your configuration stops asking for — a skill removed, or a target removed — loses the files we wrote that still hold what we wrote, and then the directory if that left it empty. A file you changed or added stays, because those bytes are the only copy of that work, and the directory is reported on every sync until it is empty. --force does not remove it: nothing is in the way of a removal, and nothing that differs from what we wrote is ever deleted. To see what a sync would change, run to11 skill list. It decides every skill the way a sync without flags does, and writes nothing. It does not preview a sync’s flags: a skill --force would replace shows as blocked or changed, one --prune would remove shows as gone, and nothing shows what --remove-all would remove. Conflicts — --prune with --remove-all; --non-interactive with --interactive.
Each location says where it delivers, once. Its header names the folders and the agents that read each one; a row names a folder only when the skill reached some of them and not others. ✓ arrived, ↑ moved to a newer version, − went away on this run, ! needs you. A skill your configuration disables is counted, not listed: the summary says 3 disabled, on every run, and no row repeats it. The run that takes back a copy it installed says so once: − legacy-migration disabled in your configuration — removed. to11 skill list still names every disabled skill. A skill nobody has stored a version of is a row of its own: <project> has it, but no version is stored yet, counted as not published in the summary. A skill you picked that the project no longer publishes reads no longer published — kept v<n>; `to11 skill sync --prune` removes it; the copy stays until you answer the question above or pass --prune, and the removal reads no longer published — removed. One row per skill. A skill written the same way into several targets is one row; a row that would say something different in one target — blocked there, or a removal naming its own path — stays a row of its own. The counts follow the rows, and in sync counts skills whose every target already matched. --format json keeps one object per skill and target. Names your own skills already use are one block per location rather than a row each: how many, which, what holds them — a to11 skill your home follows, or a folder another tool put there — and the fix. The summary counts them as not installed. Where the rows came from. When every row comes from one project, the summary ends with · from <project>; the rows do not repeat it. When locations follow different projects, as above, each location’s header says its own with a from line. A location that follows several projects names the project on each row. The summary counts what did not change as well as what did. 1 updated on its own does not say whether that was one skill out of one or one out of forty, so a run that changed something also says how many already matched their configuration. Those skills get no line of their own — a person reading this wants the diff, and the count is the context the diff is missing. A sync that changes nothing prints one line saying so: an empty terminal is indistinguishable from a crash. There is no count on that line, because the words already carry it. When nothing you follow publishes any skill, that line is no skills to install — nothing you follow publishes any yet instead of nothing to do, because “everything already matches” reads as having your skills. When every entry receives no skill by its own choice, as one linked without skills does, it is no skills to install — the configuration picks none; `to11 link` picks some.

--remove-all is how you get out

Removal is a sync whose desired state is empty, so it takes the same path and the same report as any other sync. Does — remove every skill installed in the current context, and name every path it touched. A file you changed or added is left, with its directory, exactly as when a single target is dropped — and a directory the CLI cannot read is left whole. Each stays recorded, and is named on every run, until the directory is empty; the run after that removes it and the record. With nothing left to hold, the state file is cleared. Does not — touch anything not in the state file; delete your configuration or your refresh hooks. Those are one file each, and deleting a file you own is not something a sync should do quietly. It works in the current context only, and never scans the disk. Removal in a repository removes that repository’s; removal at home removes home’s. The platform is untouched, so onboarding again restores everything you can still access.

to11 skill list

Does — report, per location, every skill the CLI manages, every skill your configuration names but does not install, every skill the project you picked skills from has that you did not pick, and every skill directory that is not ours; each with one state and where it came from. Does not — browse the catalog beyond the project your picks follow; fetch bodies; install; write anything; print an empty list when nothing is configured. Absent skills are listed by default. A skill configuration names but that is not on disk is a row with a state, and that state is the only answer to why is a skill I expected missing.
Each location is printed under the header sync prints for it, which names its folders once and the agents that read them, and its skills are grouped by the project they come from. What sits in a skills folder without coming from a project is last, under not from to11. One row per skill. A row names target folders only when the skill is not the same in every folder the header names — a skill you changed in one of them is a row per state, each naming its folders:
A row spells its folders as the header does: ./ in a repository, ~/ at home. A row says from <workspace/project/skill> only when a prefix renamed it, since the name otherwise says it. The state says what the next sync would do, not what a sync did: to install, to update, to remove, or the state that holds the skill (unchanged, blocked, disabled, …). A row about to be removed says why: no longer configured, or disabled when your configuration still names the skill and disables it. Rows that need doing come first, then steady states. The states table lists every word. --format json keeps the state names (installed, removed, conflict, …) and one object per skill and target. Disabled skills are one line of names under their project, every one of them: the same fact about each, and for most catalogs most of the list. Available skills are one line of names too. An entry with no project label receives only the skills it names, so a skill stored in the project later never arrives. list names those under available, counts them in the summary (2 available, not among the location’s skills), and ends with Next: `to11 link` lists the available skills unticked; tick one to receive it. on stderr — to11 link --global for your home’s skills when you run it inside a repository. Nothing installs them, and to11 skill sync does not mention them. An entry that pins a skill to a version, or that picks none, has nothing available.
A pin behind latest names the line that holds it. For each configuration file that pins skills at a version older than latest, list adds one line on stderr:
Up to three skills are named, joined with and (audit-runbook and house-style are pinned …); more are counted (5 skills are pinned …). A pin at the version latest points at is not mentioned. The file named is the one whose pin decided the row: an enforced pin in your home’s file decides a repository’s row too. A pin in an entry with no project label is reported the same way. No command lifts a pin: writing label: latest in place of the version: is the unpin. Deleting the line is not the same: in an entry with no project label, the version: is what picks the skill, and without it the skill is no longer received. --expand folds nothing: every skill is a row per folder, each naming its folder, disabled and available skills included — an available one reads latest · 3 available — under the same headings. The summary is the same either way. The summary counts skills, not rows, with the same words as the states. on disk is how many of the skills to11 installed are on disk now; a folder deleted by hand is not counted. At a terminal the list is in color — the location and project headings bold, skill names cyan, what the next sync would write green, states that need you yellow, and steady states, disabled and available skills and the agents in the header gray — and never when it is piped or NO_COLOR is set. Skills you have are listed before disabled ones. There is no --location or --state filter: the headings say both.

to11 skill import

Takes in the skill folders to11 did not deliver — in this repository’s targets and your home’s, or your home’s only with --global or outside a repository. to11 link runs the same step for the location it links, after it writes the file. Does — in each linked location, list every directory in the targets that holds a SKILL.md, is not a symbolic link, is not one to11 delivered, and is not named in a skills.sh lockfile (skills-lock.json at the repository root, ~/.agents/.skill-lock.json for home); compare each with that location’s project, target by target; act on each through a question or a flag. A location that is not linked has its default folders listed, for to11 link to take in. Does not — run where no location it lists is linked; act on a folder in a location that is not linked; read directories outside the configured targets (or the default ones, for a location not linked); follow a link; touch a folder skills.sh installed, a symbolic link, a bare <name>.md document, or a folder holding a skill the project has but this location does not receive (its entry does not pick it), which are counted and left alone — the last as not received here, since no sync touches it; untrack a folder git already tracks, which it names the command for instead. Conflicts — --non-interactive with --interactive; --skip with each of --adopt, --upload, --keep and --take. Both locations. Inside a repository the repository is listed first, then your home, each block headed by its location and the project it is compared with; each location’s folders go to its own project. --project keeps the locations that follow that project. Without it, a location whose file names several projects is set aside with one line naming the --project command that lists it — unless it is the only linked location, which is refused as before. A location that is not linked is listed as not linked: nothing acts on its folders, and at a terminal, once the others are done, it asks Your home is not linked. Link it to a project to import these skills? — Yes runs to11 link --global, which ends with this import for your home.
One name in one project is one skill. When both locations follow one project and each holds a folder of one name, both rows say so. The repository is answered first; once it uploads the skill, your home’s copy is taken in as that version — following latest, which now points at it, as an upload does, with its Adopted line naming your home’s file when that file’s pin moved or it gained the skill — when it is identical, and asked about as differing when it is not. A --keep naming that copy keeps it out instead, disabling the skill in its location, even while the project does not have the skill yet. Flags naming both copies for upload are refused before anything is done when their files differ, and flags never store two versions of one name in one project in one run: a copy one still reaches is refused, or left as it is when it sits beside one taken in. Only an answer at a terminal that names the next version stores it. A flag names a folder by its slug, or by its path: ./… in the repository, ~/… in your home. A slug waiting in both locations is refused before anything is done, naming both paths — without a terminal as ambiguous_skill, with a step for each folder the flag can act on. When it can act on neither, the refusal is that folder’s own reason. Each folder is one of three. Its files are compared with the files the platform renders for its target — name by name and SHA-256 by SHA-256, leaving out the .gitignore to11 writes and any local dot-prefixed file the render does not carry; a dot-prefixed file the render does carry is compared like the rest — trying the newest first, then the rest. The platform generates each delivered SKILL.md — its name, its description and a line naming the version — so only a folder to11 delivered can be a match: one whose record was lost, for example after ~/.to11 was deleted. A hand-written folder is differs or new. An upload is exactly a to11 skill store --dir. It writes the location’s skills.yaml only where following latest would not already deliver the version, and takes the folder over as the installed copy. An upload becomes the skill’s latest, which whoever follows latest receives on their next sync. When the location’s file pins the skill with version:, the pin moves to the uploaded version and the outcome line says so: ✓ Uploaded my-notes v2 → acme/web (now latest, pinned in ./.to11/skills.yaml). A new folder whose SKILL.md carries no description cannot be uploaded and is listed with needs a description in SKILL.md. A slug the platform refuses is reported on its own line and the others go on. Keep never disables a copy to11 already owns. When the same skill is a match in one target and differs in another, the matching copy is adopted, and keep mine then leaves the differing folder exactly as it is instead of writing disabled: true, which would disable the skill in every target and make the next sync remove the adopted copy. The other targets go on receiving the published skill, and the sync reports the kept folder as blocked until you move it or replace it:
Take deletes the folder’s files. It is what to11 skill sync --force does, for one skill. Without a terminal it needs --yes; at one it asks first. With a flag naming a folder it asks nothing, acts on the folders the flags name, and leaves every other folder as it is. Every name is checked before anything is done. At a terminal without one it adopts every match, asks one multi-select for the new folders with none selected, and one question per skill that differs, defaulting to keep mine. Without a terminal and without one it stops with unmanaged_skills and writes nothing. --yes alone is not an answer: a folder’s fate is a data question. A skill already disabled under the project is not asked about again.
The classification is stdout; the ✓ lines and the Next: line are stderr. A skill in more than one target is one skill: the heading counts skills, and adds the folders when there are more of them (Found 3 skills in 4 folders already in ./.claude/skills, ./.agents/skills), and what was left alone is counted the same way. Inside a repository, adopting, uploading or taking a folder git already tracks leaves files to11 now manages in the repository’s index. When the run ends, one hint names every such folder and the one command that stops the repository carrying them. The CLI never runs that command: a repository may commit its skills on purpose, for agents and colleagues who read them without to11. The hint asks you to commit what to11 rewrote only when it wrote over tracked files. Adopting a folder identical to a published version writes over nothing tracked, unless the folder has a committed .gitignore of its own, which the adoption replaces.
Under --format json stdout is one row per folder:
class is match, differs, new, or unlinked for a folder in a location that is not linked. outcome is adopted, uploaded, kept, took, left or refused, and reason says why a folder was refused or what it needs. location is repo or home; project is absent for a location that is not linked. next is the one command that acts on the folder from here — a terminal’s default answer, or to11 link --global — and is absent when the folder needs an edit first or was uploaded: an upload leaves no next step.

to11 skill store

Pushes a new version upstream. It moves the skill’s one label, latest, so everyone whose configuration follows latest receives the version on their next sync; a machine pinned to a version keeps that version. Does — take a slug and a content source; create the skill if it does not exist; save a new version; put that version on this machine; make your configuration receive it, writing as little as that takes; report whether the skill was created or a version added. It also converts what it reads into the one stored text form before posting: CRLF becomes LF, a byte-order mark is dropped, and a file that is not valid UTF-8 is reported rather than sent. A Windows folder imports without anyone editing it by hand. Does not — keep a version private — a store is a publish; overwrite an earlier version — a version is immutable and store only ever adds; turn a skill into a chat prompt or the reverse; guess a description for a new skill. Conflicts — exactly one of --dir, --from, --body is required. The description’s source depends on the content source. Creating takes it from --description, falling back to the entry document’s frontmatter — with any source, because --from and --body are stored as a SKILL.md as well. A new skill with neither is the error; the flag alone is not required. On a skill that already exists, --from and --body take it from the flag, while --dir takes it from the entry document and prints --description ignored: the entry document carries the description of an imported directory. A directory is the skill’s own record of what it is, so the flag cannot quietly disagree with the file the agent reads. An entry document carrying no description updates nothing and leaves the stored one standing. Creating and adding are reported differently, and that is the guard against a typo:
Every store ends on that last line: the version is latest, and whoever follows latest receives it on their next sync. A mistyped slug creates a new skill rather than failing, so the word created is what tells you that you meant stored. The new skill carries latest, so a project entry following latest receives it on the next sync; the recovery is to store into the right slug and archive the stray one from the project’s Skills page. A slug belongs to whichever kind claimed it first. A project holding a chat prompt called code-review cannot also hold a skill called code-review, so a store can fail on a name you have never used for a skill:
The way out only runs one way. A skill’s slug can be changed and a chat prompt’s cannot, so the skill is what moves aside — which is also the thing nobody depends on yet. The version you just stored is what lands on disk. It is also what latest now points at, so a configuration that follows latest already receives it, and store writes nothing into it. A later store by anyone moves latest on, and the next sync on this machine writes that version too. An edit you make to the files on disk is not overwritten either: sync skips a skill you changed, and that takes no pin. Your configuration changes only where it would not receive the version. Per entry in the skills.yaml the store ran against: A pin you already had is your hold, so it moves with you, and the output says so:
--format json carries the same fact as pinnedIn, the configuration file whose pin moved; it is absent when the configuration follows latest. See to11 skill store output. There is no command to unpin. A pin is a line in a file you own: write label: latest in place of the skill’s version: to follow latest again. A skill added to an entry that picks its skills is said too, on stderr: added incident-triage to ~/.to11/skills.yaml, following `latest`. An import upload says it on its outcome line: (now latest, added to ./.to11/skills.yaml). The files are rendered by the platform, exactly as an installed skill is — frontmatter and all — so what you read on disk is the artifact an agent receives, not the bytes you uploaded. A workspace/project of another organization is stored into, and nothing else. When --organization or TO11_ORGANIZATION names an organization other than the one the configuration follows, the configuration is not changed and, without --no-install, the version is not installed:
With --no-install the line begins stored, not received here:.

to11 code

Runs the hooks the to11 plugin installs in Claude Code and Codex. It does not start an agent: run claude or codex directly. Does — run one hook mode, below: refresh skills, or send a session where auto-sync is on. Print nothing and exit zero, whatever happens. Does not — start, wrap, or route a coding agent. Without a hook mode it stops with an error and exits 1:
to11 code is left out of to11 --help’s command list, because nobody types it by hand.

Refresh hook modes

Modes an agent harness invokes to refresh skills. Not for typing by hand, and each takes no agent name. Two modes are not a refresh: Where auto-sync is on, each sends the session’s new transcript lines in the background, as to11 session sync would, and otherwise does nothing. The to11 plugin 0.5.0 runs --claude-sync-hook on both events instead; the CLI still accepts it, and it does the same. Each agent names its own, because an agent’s events are its own: Codex has no expansion event, and a point one agent fires is not the point the other fires. --refresh-hook is for an integration that is neither. Each names a mode, not an action, so what a refresh point does can change in the CLI without rewriting a file in your agent configuration. The to11 plugin is what wires them to their events; to11 link and to11 ui offer to install it. Every mode exits zero in every state, writes nothing to either stream, and emits no hook decision. A refresh does not get a vote on whether your work proceeds. Each mode starts the refresh in the background and returns at once, with one exception: --claude-session-start-hook and --codex-session-start-hook sync before returning when a configured location has never synced, so a session in a fresh clone or a new worktree starts with its skills installed. That happens once per location, whether or not the sync succeeds, and the hook waits no longer than 45 seconds plus a two-second grace. When your sign-in is about to be renewed, the session start leaves the sync to the background instead, so a renewal is never cut short.

to11 session

Prints the session subcommands.

to11 session sync

Sends the Claude Code sessions started in this repository to a project. Does — find the sessions started at the repository’s root, in a subdirectory or in one of its worktrees, by the directory each transcript records; send each with its subagents’ transcripts; send only the lines added since the last run; mask secrets before anything is sent; print how many sessions it sent, and a link to the project’s sessions. Does not — send another agent’s sessions than Claude Code’s; send a line Claude Code is still writing, which the next run sends; turn on auto-sync.
A run covers the newest sessions up to 512 MB. Newest first, by when a transcript last changed, it takes sessions while their transcripts, subagents included, come to at most --max-size together, and stops at the first that would go past it. The newest session is taken whatever its size, and --session sends the session it names whatever the size. The size counts each transcript whole, sent before or not, so a second run covers the same sessions and sends only what was added to them. Sessions past the size that still have something to send are said on stderr:
All sessions are synced. when nothing is new, and The newest sessions are synced. when nothing is new among the sessions the run covers but older ones were left out. --format json prints project, new, updated and link, and left when sessions were left out. With no project from any of these, it stops with no project for these sessions and names both ways to set one: to11 link, which writes it into .to11/sessions.yaml, or --project. At a terminal, one line on stderr fills a bar as the transcripts’ new lines are sent, and is erased before the report. ~/.to11/.sessions.state.json records how far each transcript was sent to each API and project, so a session synced to one project is sent whole to another. Sending a line again stores nothing twice, so deleting that file sends every session again from the start.

to11 session autosync

Turns automatic session sync on or off, or prints the setting that applies here. Does — write autoSync to .to11/sessions.yaml in this repository, or to ~/.to11/sessions.yaml with --global; keep the repository’s sessions.yaml out of git through the .to11/.gitignore the CLI writes, or say to add it to one your team wrote; after on, say so when no sessions.yaml names a project for the sessions; with no argument, print the setting that applies and whether it is the repository’s or the global one. Does not — sync anything itself; install the to11 plugin, whose Claude Code hooks do the syncing, though it says so when the plugin is missing. A repository’s setting comes before the global one, and the setting is off until someone turns it on. With it on, the Stop and SessionEnd hooks of the to11 plugin run their hook modes, which send the session’s new lines as to11 session sync would. The hooks come with the plugin 0.5.0; with an earlier plugin, nothing syncs automatically.

to11 open

Opens a to11 dashboard link in the default browser. The to11 plugin’s /to11-open runs it, since Claude Code gives a plugin no way to open a URL itself.
Does — open the link with the system’s own opener (open, xdg-open, rundll32), print nothing, and exit zero. Does not — open a link to anywhere else. The scheme and host must be the dashboard’s: TO11_WEB_URL, else staging under TO11_DEV, else production. So nothing steering your agent can open other pages in your browser through it. It exits 1, with the reason on stderr, when:
  • the link is not on the dashboard’s host, or the dashboard’s address is not known;
  • there is no browser on this machine: SSH_CONNECTION or SSH_TTY is set, or on Linux neither DISPLAY nor WAYLAND_DISPLAY is;
  • the opener fails. It is given two seconds, and one still running then counts as having opened the link. On Windows, rundll32 reports success either way, so a failure there is not seen.

to11 version

Does — print the CLI version and exit zero. Does not — contact the platform; check for updates; read configuration. So it answers on a machine with no configuration and no network, which is the state you are in when you are working out why nothing else works.
to11 --version prints the same thing.