---
title: "Группы команд, алиасы и подсказки"
description: "Cobra группы команд: AddGroup и GroupID в справке, алиасы Aliases, автоподсказки «Did you mean» через SuggestFor, уход команды на пенсию через Deprecated и Hidden."
course: "Cobra: CLI-приложения на Go"
url: "https://golangmaster.ru/courses/cobra/lessons/11-grupy-aliasy/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 16
---

# Группы команд, алиасы и подсказки

*Курс «Cobra: CLI-приложения на Go», урок 11 из 25. ~16 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/cobra/lessons/11-grupy-aliasy/*

Cobra группы команд выводит в справке через AddGroup, дополнительные имена даёт поле Aliases, а опечатки ловит движок подсказок «Did you mean this?». Разберём AddGroup и GroupID, Aliases и SuggestFor, порог SuggestionsMinimumDistance и достойную пенсию команды через Deprecated.

Утилита растёт, и вместе с ней растут две боли. Первая: help корня превращается в простыню из двадцати команд подряд, где setup живёт рядом с ежедневными операциями, и найти нужное — работа. Вторая: пользователь печатает notes ad вместо add, получает unknown command и либо перечитывает справку, либо уходит писать issue. Обе решаются штатными средствами Cobra, без самодельных обработчиков: секции в справке дают группы, дополнительные имена — алиасы, а опечатки ловит встроенный движок подсказок. Оба симптома видны невооружённым глазом на одном экране --help, и оба лечатся за вечер, если знать четыре поля и два метода. Отдельный случай — команды на пенсии: переименование нельзя делать рубильником, пользователи держат скрипты на старых именах, и тут нужен управляемый период устаревания. Разберём все четыре механизма в порядке появления в жизни утилиты.

### AddGroup и GroupID: группы команд в справке

Группа объявляется структурой cobra.Group: ID — внутренний идентификатор без пробелов, Title — человекочитаемый заголовок, по конвенции Cobra заканчивающийся двоеточием. rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "Работа с заметками:"}) создаёт секцию, а поле GroupID у команды привязывает её к секции по ID. В справке корня сначала печатаются команды из групп — каждая под своим заголовком, — затем оставшиеся в списке Additional Commands. Команды без группы не пропадают: они просто собираются в общий хвост. На выполнение, автодополнение и поиск команды группы не влияют — это чистая косметика справки, и заводить их имеет смысл, когда команд набирается восемь и больше: раньше секции только шумят, потом спасают. Порядок групп на странице — порядок AddGroup; порядок команд внутри группы — алфавитный, поменять его вручную нельзя. Поэтому в Title не пишут приоритеты вроде «новое» — единственный способ управлять порядком секций, это порядок их регистрации в коде.

### AddGroup и GroupID на корне

```go
var rootCmd = &cobra.Command{
        Use:   "notes",
        Short: "Менеджер заметок",
}

func init() {
        rootCmd.AddGroup(&cobra.Group{
                ID:    "core",
                Title: "Работа с заметками:",
        })
        rootCmd.AddGroup(&cobra.Group{
                ID:    "setup",
                Title: "Настройка:",
        })

        addCmd.GroupID = "core"
        listCmd.GroupID = "core"
        initCmd.GroupID = "setup"

        rootCmd.AddCommand(addCmd, listCmd, initCmd)
}
```

Два вызова AddGroup создают секции, GroupID привязывает команды по ID. В --help корня сначала пойдёт «Работа с заметками:» с add и list, затем «Настройка:» с init. ID задаётся латиницей без пробелов, а Title по конвенции kubectl и gh заканчивается двоеточием — так заголовок выглядит секцией, а не командой. Забытый GroupID оставит команду в Additional Commands, ничего не сломав.

### Проверка: группа без регистрации

**Вопрос:** У команды задан GroupID: "core", но вызов AddGroup с ID "core" забыли. Что произойдёт?

- Паника при Execute
- ✅ Команда окажется в секции Additional Commands
- Команда исчезнет из справки
- Cobra создаст группу автоматически с пустым заголовком

Группы ищутся по ID только ради отображения, и отсутствие группы ничего не ломает: команда печатается в общем списке после группированных. Справка просто не сгруппирована — проверить это можно только локально, собрав утилиту и открыв --help.

### Aliases: несколько имён одной команды

Aliases — срез строк с дополнительными именами. serveCmd.Aliases = []string{"start", "run"} — и утилита отвечает на все три: notes serve, notes start, notes run. Алиас полноценный: он находится при поиске команды наравне с основным именем, работает во вложенных путях и показывается в справке первой строкой — «run, start — Запустить сервер». Живут алиасы для трёх случаев: короткие формы частых команд, исторические имена до переименования и забота о моторной памяти пользователей соседних утилит. Мера нужна и здесь: десять алиасов на команду превращают справку в телефонную книгу, а новое имя не добавляют «на всякий случай» — каждое живёт в документации и в багтрекере. Отдельная тонкость: в bash-автодополнение по умолчанию попадает только основное имя, так что обещать пользователю «все имена работают везде» не стоит — обещайте основное, а алиасы называйте удобным бонусом. И держите алиасы стабильными: имя, которое вы дали и убрали, ломает чужие скрипты так же надёжно, как удаление команды.

### Aliases и SuggestFor в одной команде

```go
var serveCmd = &cobra.Command{
        Use:     "serve",
        Aliases: []string{"start", "run"},
        Short:   "Запустить сервер заметок",
        SuggestFor: []string{"server", "srv"},
        RunE: func(cmd *cobra.Command, args []string) error {
                return runServer()
        },
}
```

Aliases даёт два дополнительных имени: notes start и notes run выполнят ту же команду, в справке появится строка «run, start». SuggestFor — явные подсказки: пользователь напечатал server или srv, и Cobra предложит serve, даже если до порога расстояния Левенштейна далеко. RunE один — поведение идентично при любом имени.

### Что случится с notes srv

```go
// serveCmd объявлен как выше:
// Use "serve", Aliases ["start", "run"],
// SuggestFor ["server", "srv"]

_ = rootCmd.Execute()
// Вызвано: notes srv
```

**Что выведет программа?**

- Выполнится serve: srv найден через SuggestFor
- ✅ Ошибка unknown command и подсказка «Did you mean this? serve»
- Ошибка unknown command без подсказок: srv ни на что не похож
- Выполнится serve: srv — алиас

SuggestFor — только подсказки, не алиасы: srv не выполнится, но попадёт в предложение «Did you mean this?». Выполнится команда по алиасу start или run, а srv лишь укажет на serve.

### «Did you mean this?»: автоподсказки опечаток

За подсказки отвечает движок в поиске команды: когда введённое имя не найдено, Cobra обходит соседей и считает расстояние Левенштейна между тем, что напечатали, и каждым именем. Порог задаёт SuggestionsMinimumDistance, по умолчанию 2; вдобавок работает префиксное совпадение: если имя начинается с введённого, подсказка сработает независимо от дистанции. Результат выглядит как знакомый по kubectl вывод: unknown command и ниже — Did you mean this? add. Порог поднимается одной строкой rootCmd.SuggestionsMinimumDistance = 3 для «толстых пальцев», но выше трёх залезать не стоит: подсказки начнут предлагать далёкие команды и перестанут помогать. Полное отключение — DisableSuggestions: true; для скриптов, где лишний вывод мешает парсингу, это оправдано, в человеческих утилитах — редко. Предложение ничего не выполняет: пользователь обязан перебить команду сам, за автозамену тут никто не отвечает.

### Вывод при опечатке

```go
$ notes ad "встреча в 15:00"
Error: unknown command "ad" for "notes"
Run 'notes --help' for usage.

Did you mean this?
        add
```

Ошибка печатается в stderr, подсказка идёт после неё: имя с отступом, а при нескольких кандидатах заголовок меняется на «Did you mean this?» со списком. Подсказка не меняет поведение команды — она только текст; за саму ошибку и код выхода отвечает то, что мы разбирали в командах и будем усиливать в уроке про коды выхода.

### Проверка: какой механизм сработает

**Вопрос:** Пользователь печатает notes rm — команды rm нет, но есть remove. Расстояние Левенштейна между rm и remove равно 4. Что нужно, чтобы Cobra предложила remove?

- Ничего: rm и remove совпадают префиксом
- ✅ SuggestFor: []string{"rm"} у команды remove
- Поднять SuggestionsMinimumDistance до 6
- Добавить rm в Aliases — тогда сработает подсказка

Префикс не совпал — remove не начинается с rm, а дистанция 4 выше порога 2. SuggestFor честно объявляет: «с такой привычкой пользователи приходят сюда». Алиас помог бы выполнить rm, но подсказки он не питает — SuggestionsFor для этого и существует.

### Как Cobra ищет команду: поиск и кандидаты

Полезно понимать, где в этом механизме живёт поиск. Внутри Execute вызывается Find: он спускается по дереву команд, сопоставляя каждый следующий аргумент с именем или алиасом дочерних команд. Пока совпадение есть — путь продолжается; как только аргумент не совпал ни с одной командой, срабатывает ветка с suggestions: строится список кандидатов по дистанции, префиксу и SuggestFor, и всё это попадает в сообщение об ошибке. Отсюда два практических вывода. Первый: подсказки видят только команды, зарегистрированные в дереве через AddCommand, — незарегистрированная команда не подсказывается никогда. Второй: алиас участвует в поиске, но не в подсказках — кандидаты собираются по основному имени и SuggestFor, и это ещё один аргумент к тому, чтобы SuggestFor заполнять для команд с историческими именами.

### Deprecated и Hidden: уход команды на пенсию

Переименование команды — ритуал с тремя шагами, и Deprecated — первый. Полю Deprecated ставят человеческий текст: Deprecated: "используйте notes add". Cobra печатает предупреждение при каждом вызове, команда продолжает работать, а из справки и автодополнения исчезает: новые пользователи её не увидят, старые получают время на переезд. Второй шаг — через пару релизов поле снимается, а старое имя переезжает в Aliases: вызовы работают молча, без предупреждений. Третий — в мажорной версии алиас удаляется совсем. Поле Hidden: true — другой инструмент: команда жива и работает, но не показывается в справке и дополнении; так прячут внутренние команды для скриптов и отладочные хвосты. Не путайте смыслы: Deprecated — «уйдёт, переходите на новое», Hidden — «существует, но вам знать не положено». Первое про миграцию, второе про границы публичного интерфейса. Мой любимый порядок действий при переименовании: сначала Deprecated на старом имени, затем — в следующем релизе — перенос в Aliases, и только потом удаление; спешка на любом шаге превращается в чужие сломанные скрипты в CI.

### Устаревающая команда с общим RunE

```go
var addOldCmd = &cobra.Command{
        Use:        "new",
        Short:      "Добавить заметку (устарела)",
        Deprecated: "команда new устарела — используйте notes add",
        Aliases:    []string{"create"},
        Hidden:     false,
        RunE: func(cmd *cobra.Command, args []string) error {
                return runAdd(args)
        },
}
```

Deprecated печатает предупреждение перед выполнением и не мешает работе: скрипты на старом имени продолжают жить. Команда исчезает из --help и автодополнения, так что новички не начнут с устаревшего пути. RunE общий с новой командой — поведение идентично, разница только в уведомлении; это и делает миграцию предсказуемой.

> **Предупреждение — в stderr, вывод — в stdout.** Предупреждение об устаревании печатается перед выполнением и должно оставаться машинно-читаемым по месту: не пишите его в stdout и не украшайте цветом. Скрипты, парсящие результат команды, сломаются ровно в тот момент, когда вы предупреждали о переименовании. Разделение потоков и коды выхода при ошибках — тема урока про [ошибки и коды выхода](/courses/cobra/lessons/14-oshibki-exit-codes/).

### Четыре механизма рядом

| Механизм | Что делает | На что не влияет |
| --- | --- | --- |
| AddGroup + GroupID | секции в справке корня | выполнение и автодополнение |
| Aliases | дополнительные имена, работает поиск | автодополнение по умолчанию |
| SuggestFor | явные подсказки «Did you mean» | выполнение: srv не запустит serve |
| Deprecated | предупреждение + скрытие из справки | работоспособность команды |
| Hidden | скрытие из справки и дополнения | работоспособность команды |

### Сводка: когда что применять

Практическая раскладка по жизненному циклу утилиты выглядит так. Восемь команд и больше — заводите группы и назначьте GroupID каждой новой команде сразу, это дешевле задним числом. Частые команды с длинными именами — один-два алиаса, и только те, что сами используете. Растёт поток issue с опечатками — поднимите порог на единицу и добавьте SuggestFor для предсказуемых промахов. Переименование — Deprecated сегодня, алиас через два релиза, удаление в мажорной версии. Внутренние команды — Hidden с первого дня, пока они не обросли зависимостями. Каждый пункт проверяется одной командой локально: соберите утилиту, опечатайтесь, позовите старое имя и посмотрите --help — все четыре механизма видны на экране без отладчика. Нормальная скорость для утилиты среднего размера — вечер с чаем: группы и алиасы занимают минуты, Deprecated с миграцией — полчаса вместе с текстом предупреждения.

### Соберите группу и алиасы

Впишите метод регистрации группы, ID и поле алиасов.

```go
rootCmd.___(&cobra.Group{ID: "core", Title: "Основные команды:"})

var addCmd = &cobra.Command{
        Use:     "add",
        GroupID: "___",
        ___:     []string{"create", "new"},
}
```

Подсказка: Группа регистрируется AddGroup, GroupID ссылается на её ID, дополнительные имена — поле Aliases.

Правильные ответы в пропусках: `AddGroup`, `core`, `Aliases`

### Соберите определение команды из шести строк

Расставьте: объявление, имена, алиас, подсказки, группа, закрытие структуры.

Правильный порядок строк:

1. `var addCmd = &cobra.Command{`
2. `  Use:     "add",`
3. `  Aliases: []string{"create"},`
4. `  SuggestFor: []string{"new"},`
5. `  GroupID: "core",`
6. `}`

### Карточки: группы, алиасы, подсказки

- **AddGroup** — Секция справки: cobra.Group{ID, Title}. Заголовки с двоеточием по конвенции kubectl и gh; порядок групп — порядок AddGroup.
- **GroupID** — Привязка команды к группе по ID. Без группы или с забытым AddGroup команда попадает в Additional Commands.
- **Aliases** — Дополнительные имена команды. Выполняются как основная, видны в справке; в bash-автодополнение по умолчанию не попадают.
- **SuggestFor** — Явные подсказки «Did you mean»: срабатывают, даже когда расстояние Левенштейна больше порога. Выполнение не запускает.
- **SuggestionsMinimumDistance** — Порог расстояния Левенштейна для подсказок, по умолчанию 2. Префиксное совпадение подсказывает независимо от порога.
- **Deprecated и Hidden** — Deprecated: предупреждение при вызове, скрытие из справки, команда работает — путь к переименованию. Hidden: молчаливое скрытие без предупреждений.

### Что дальше

Справка корня теперь сгруппирована, и настала очередь самой страницы справки: в уроке о [кастомизации help и usage](/courses/cobra/lessons/12-help-usage/) разберём шаблоны SetHelpTemplate, SetUsageFunc и секции Long и Example, из которых эта страница складывается. Подсказки «Did you mean» — про команды; про аргументы отвечает автодополнение, и ему посвящён отдельный урок про [completion для bash, zsh и fish](/courses/cobra/lessons/17-autocompletion/). Обзор курса — на странице [Cobra](/courses/cobra/). И стандартная оговорка: все четыре механизма видны только локально — соберите утилиту, опечатайтесь и позовите устаревшее имя; песочница терминальный ввод не эмулирует. Зато перенос этих механизмов в свой проект не требует ничего сверх уже установленной библиотеки: все четыре живут в полях структуры cobra.Command и двух методах корня.

## Коротко: что запомнить

- AddGroup создаёт секцию справки, GroupID привязывает команду по ID; группы — косметика, на выполнение они не влияют.
- Команды без группы собираются в Additional Commands; порядок внутри группы алфавитный.
- Aliases даёт дополнительные имена: они работают в поиске и справке, но не попадают в автодополнение по умолчанию.
- SuggestFor добавляет явные подсказки «Did you mean» там, где расстояние Левенштейна больше порога.
- SuggestionsMinimumDistance по умолчанию 2; префиксное совпадение подсказывает независимо от дистанции.
- Deprecated печатает предупреждение, скрывает команду из справки и не ломает скрипты; Hidden молчит и просто прячет.
- Переименование — ритуал: Deprecated сегодня, Aliases через два релиза, удаление в мажорной версии.

## Домашнее задание

Добавьте в свою утилиту две группы — «Работа с заметками» и «Настройка» — и разложите команды по GroupID. Затем сделайте алиасы для двух самых частых команд, а самую старую команду переведите в Deprecated с человеческим текстом предупреждения. Проверьте локально: --help показывает секции, опечатка вроде notes ad получает подсказку, устаревшее имя работает с предупреждением.

## Вопросы и ответы по уроку

### Как сгруппировать команды в справке Cobra?

rootCmd.AddGroup(&cobra.Group{ID: "core", Title: "Основные команды:"}) и поле GroupID: "core" у каждой команды группы. Команды без группы попадут в Additional Commands. Группы влияют только на отображение справки.

### Почему Cobra не предлагает команду при опечатке?

Либо расстояние Левенштейна больше порога SuggestionsMinimumDistance (по умолчанию 2), либо нет префиксного совпадения. Добавьте нужное имя в SuggestFor команды — это явный список подсказок, который работает независимо от дистанции.

### Чем Deprecated отличается от Hidden?

Deprecated печатает предупреждение при каждом вызове и прячет команду из справки — это путь переименования с миграцией пользователей. Hidden молча скрывает команду из справки и автодополнения без предупреждений — это для внутренних и отладочных команд.
