Где что лежит
Три отдельные директории, намеренно не смешиваются друг с другом — конфигурация, извлечённые бинарники и логи никогда не попадают в одно и то же место.
| Путь | Назначение |
|---|---|
~/.config/som/settings.json | Ваша конфигурация. Создаётся из платформо-специфичного шаблона при первом запуске. Отслеживается и перезагружается на лету — правки применяются мгновенно, при невалидном JSON показывается баннер с ошибкой прямо в приложении. |
~/.config/som/themes/nord.json | Встроенная тема «Nord», записывается на диск при первом запуске. |
~/.config/som/db.json | Раскладка табов/сплитов/сессий, перезаписывается при каждом изменении таба/сплита и при выходе. Руками редактировать не стоит; описан ниже для диагностики. |
~/.local/share/som/ffmpeg/ (только Windows) | Встроенные библиотеки декодирования FFmpeg, автоматически извлекаются при первом запуске для видеоплеера. Предоставлять их самостоятельно не нужно. |
~/.local/share/som/conpty/ (только Windows) | Собственный патченый ConPTY-бэкенд Som, автоматически извлекается при первом запуске. |
~/.local/state/som/logs/ | Ежедневные лог-файлы. Первое место для проверки, если что-то работает не так, как ожидалось. |
На macOS/Linux пути для извлечённых бинарников и логов следуют собственным XDG-подобным соглашениям платформы (~/Library/Application Support/Som и ~/Library/Logs/Som на macOS; $XDG_DATA_HOME/som и $XDG_STATE_HOME/som на Linux) — одинаковым везде остаётся только ~/.config/som (settings/db/темы).
somsrv (бинарник, который деплоится на удалённые хосты для SSH-сессий с "tmux": true) копируется из встроенной в Som копии сразу во временный файл на время одного деплоя — ничего постоянного на диске для него не остаётся.
Справочник settings.json
Все поля опциональны; всё, что вы не укажете, откатывается к дефолту для вашей платформы. Неизвестные ключи молча игнорируются (без ошибки), так что опечатка в имени ключа вас не предупредит — сверяйте написание с этой таблицей.
Два поведения зафиксированы и не настраиваются: звуковой сигнал терминала всегда отключён (нет настройки для системного звука), а копирование по выделению (автокопирование выделенного текста в буфер обмена) всегда включено.
window
| Ключ | Тип | Эффект |
|---|---|---|
window.theme | строка | Имя активной темы (например, "Nord Dark"). Применяется корректно. |
window.mode | "windowed" (умолч.) / "maximized" / "minimized" / "fullscreen" | Начальное положение окна, применяется при каждом запуске (не только при первом). "windowed" запоминает позицию/размер в db.json — перемещение или изменение размера окна обновляет это автоматически. Если геометрия ещё не была запомнена, по умолчанию берётся размер экрана минус 100px по каждому измерению, с позицией 50px от левого верхнего угла. window.position/window.size (ниже) могут это переопределить. |
window.position.{top,left} / window.size.{width,height} | число, физические пиксели | Явные позиция/размер при старте, применяются только когда window.mode = "windowed". Срабатывают только если заданы одновременно position и size, и все четыре их поля ненулевые — если хоть одно отсутствует или равно 0, всё игнорируется целиком и используется запомненная в db.json геометрия. Не запоминаются/не обновляются впоследствии — перемещение или изменение размера окна всё равно обновляет только db.json, поэтому эти значения будут применять одну и ту же фиксированную геометрию при каждом следующем запуске, пока остаются заданы. |
window.padding.{top,bottom,left,right} | число, пиксели | Отступ между краем окна ОС и областью терминала/сплитов с этой стороны. Заголовок окна и полоса табов всегда прижаты к краю окна независимо от этой настройки. 0 (по умолчанию) означает отсутствие отступа. |
window.selection | hex-строка, например "#88c0d0" | Цвет подсветки выделения в терминале (фон за текстом, выделенным мышью). Заодно перекрашивает несколько других акцентных элементов UI (например, подсветку совпадений поиска), поскольку использует общий цвет темы text.accent, а не отдельный терминальный. |
log
| Ключ | Тип | По умолчанию | Эффект |
|---|---|---|---|
log.level | строка | "all" ("trace" в Windows-шаблоне) | Уровень фильтрации логов, читается один раз при старте. |
log.days | число | 7 | Только Windows: сколько дней ротированных лог-файлов хранить. |
font
| Ключ | Тип | Эффект |
|---|---|---|
font.face | строка | Семейство шрифта терминала И интерфейсного буфера. |
font.size | число | Размер шрифта терминала (px). |
font.weight | целое, 100-900 | Насыщенность шрифта терминала И интерфейсного буфера (400 = обычный, 700 = жирный). Значения вне диапазона обрезаются. |
font.lineHeight | число | Множитель высоты строки терминала. |
font.features | объект | OpenType-фичи шрифта — см. «Лигатуры и фичи шрифта» ниже. |
Лигатуры и фичи шрифта
font.features сопоставляет 4-символьный тег OpenType-фичи либо булеву значению (true/false, включить/выключить), либо целому числу (для фич с несколькими вариантами, например стилистических наборов):
"font": { "face": "FiraCode Nerd Font", "features": { "calt": true, "cv02": 1, "cv01": 7 } }
calt — стандартный OpenType-тег для контекстных альтернатив, именно его используют большинство шрифтов (включая FiraCode, Cascadia Code, JetBrains Mono) для отрисовки лигатур вроде ->, =>, !=, >=, && как единых слитных глифов. Лигатуры по умолчанию выключены — задайте "calt": true, чтобы включить их (сам шрифт должен поддерживать лигатуры; Som их не синтезирует). Невалидные теги (не ровно 4 буквенно-цифровых символа) или невалидные значения (что угодно, кроме булева или неотрицательного целого) логируются и пропускаются, не ломая остальные настройки.
cursor
| Ключ | Тип | Эффект |
|---|---|---|
cursor.shape | "block" / "bar" / "underline" / "hollow" | Форма курсора. |
cursor.color | hex-строка | Цвет курсора. |
cursor.blinking | "on" / "off" / что угодно ещё | "on"/"off" применяются буквально; любое другое значение означает «управляется терминалом» (мигание следует escape-последовательностям самого приложения в шелле). |
scroll
| Ключ | Тип | По умолчанию | Эффект |
|---|---|---|---|
scroll.scrollMultiplier | число | 3.0 | Множитель скорости прокрутки колесом мыши. |
scroll.maxScrollHistory | число | 10000 | Лимит строк scrollback (0 отключает прокрутку; внутренне ограничен 100 000). |
scroll.alternateScroll | "on" / "off" | "on" | Отправлять ли колесо мыши как стрелки внутри alt-screen приложений (vim, less, htop). |
tabs
Упорядоченный массив профилей табов. Голое действие NewTab (Ctrl+Shift+=/Cmd+Shift+= в поставляемых дефолтах) открывает профиль по умолчанию: тот, что помечен "default": true, либо tabs[0], если ни один не помечен. Записи 2-9 доступны через Ctrl+Shift+2..Ctrl+Shift+9 в Windows-шаблоне независимо от того, какой профиль дефолтный (шаблоны macOS/Linux сейчас подключают только профиль 1).
"tabs": [ { "name": "shell", "icon": "", "shell": "$SHELL", "home": "~" }, { "name": "server", "shell": "ssh myhost", "home": "~", "tmux": true, "default": true } ]
| Ключ | Тип | По умолчанию | Эффект |
|---|---|---|---|
name | строка | "" | Заголовок таба и подпись в выпадающем списке профилей. |
icon | строка | нет | Глиф, показываемый на табе (лучше всего работает с Nerd Font — см. font.face). |
shell | строка | системный шелл | Команда для запуска. Поддерживает обычные шеллы, вызовы ssh <host> и wsl. |
home | строка | нет | Рабочая директория; ~ разворачивается. Должна указывать на существующую директорию, иначе игнорируется. |
tmux | bool | false | Включить бэкенд somsrv для этого профиля — сохраняет сессию живой между перезапусками Som. См. somsrv. |
default | bool | false | Помечает этот профиль как тот, что открывает кнопка +/голое действие NewTab, вместо tabs[0]. Пометить так можно не более одного профиля — settings.json не парсится (откат к встроенным дефолтам с баннером «Invalid settings.json»), если помечено больше одного. |
keys
Плоская карта сочетание-клавиш → имя действия. Пользовательские записи объединяются с платформенными дефолтами по ключу (нужно перечислить только те клавиши, которые хотите изменить или добавить; остальное сохраняет дефолт).
"keys": { "ctrl-shift-=": "NewTab", "ctrl-shift--": "CloseTab", "ctrl-shift-left": "PrevTab" }
Распознаваемые имена действий: Copy, Paste, CloseTab, NewPane, ClosePane, NextPane, PrevPane, NextTab, PrevTab, Quit, IncreaseFont, DecreaseFont, ResetFont, NewTab, NewTab1..NewTab10. Любая другая строка молча игнорируется — привязка не создаётся, ошибка не показывается, так что сверяйте написание внимательно по этому списку.
NewTab1..NewTab10 открывают tabs[0]..tabs[9] по позиции — если в settings.json меньше профилей (например, NewTab9 при всего 5 записях в tabs[]), нажатие этой клавиши покажет уведомление «No profile #9…» вместо того, чтобы молча открыть другой профиль. С голым NewTab так случиться не может: он всегда резолвится в дефолтный профиль, который гарантированно существует.
Соглашение об именовании: специфичные для Som действия табов/панелей (NewTab*, CloseTab, NewPane, ClosePane, PrevPane/NextPane, PrevTab/NextTab) задуманы на сочетаниях Ctrl+Shift+* в поставляемых дефолтах, чтобы не конфликтовать с Copy/Paste/Quit/шрифтовыми сочетаниями, которые следуют стандартным системным конвенциям без Shift.
Синтаксис сочетаний следует конвенциям GPUI: строчные буквы, модификаторы через дефис, например ctrl-shift-c, cmd-v, alt-f4.
Горячие клавиши по умолчанию
Windows
| Ctrl+Insert / Ctrl+Shift+C | Копировать |
| Shift+Insert / Ctrl+V | Вставить |
| Ctrl+= / Ctrl+- / Ctrl+0 | Увеличить / уменьшить / сбросить размер шрифта (только на сессию) |
| Ctrl+Scroll | Масштаб шрифта колесом мыши (только на сессию) |
| Ctrl+Shift+= | Новый таб из профиля по умолчанию |
| Ctrl+Shift+1…Ctrl+Shift+9 / Ctrl+Shift+0 | Новый таб из профиля 1-9 / профиля 10 |
| Ctrl+Shift+- | Закрыть активный таб |
| Ctrl+Shift+\ | Разделить активную панель (новый сплит) |
| Ctrl+Shift+Backspace | Закрыть активную панель сплита |
| Ctrl+Shift+Up / Ctrl+Shift+Down | Фокус на предыдущую / следующую панель сплита |
| Ctrl+Shift+Left / Ctrl+Shift+Right | Активировать предыдущий / следующий таб |
| Alt+F4 | Выход |
macOS
| Cmd+C | Копировать |
| Cmd+V | Вставить |
| Cmd+= / Cmd+- / Cmd+0 | Увеличить / уменьшить / сбросить размер шрифта (только на сессию) |
| Cmd+Scroll | Масштаб шрифта колесом мыши (только на сессию) |
| Cmd+Shift+= | Новый таб из профиля по умолчанию |
| Cmd+Shift+1…Cmd+Shift+9 / Cmd+Shift+0 | Новый таб из профиля 1-9 / профиля 10 |
| Cmd+Shift+- | Закрыть активный таб |
| Cmd+Shift+\ | Разделить активную панель (новый сплит) |
| Cmd+Shift+Backspace | Закрыть активную панель сплита |
| Cmd+Shift+Up / Cmd+Shift+Down | Фокус на предыдущую / следующую панель сплита |
| Cmd+Shift+Left / Cmd+Shift+Right | Активировать предыдущий / следующий таб |
| Cmd+Q | Выход |
Linux
| Ctrl+Insert / Ctrl+Shift+C | Копировать |
| Shift+Insert / Ctrl+V | Вставить |
| Ctrl+= / Ctrl+- / Ctrl+0 | Увеличить / уменьшить / сбросить размер шрифта (только на сессию) |
| Ctrl+Scroll | Масштаб шрифта колесом мыши (только на сессию) |
| Ctrl+Shift+= | Новый таб из профиля по умолчанию |
| Ctrl+Shift+1…Ctrl+Shift+9 / Ctrl+Shift+0 | Новый таб из профиля 1-9 / профиля 10 |
| Ctrl+Shift+- | Закрыть активный таб |
| Ctrl+Shift+\ | Разделить активную панель (новый сплит) |
| Ctrl+Shift+Backspace | Закрыть активную панель сплита |
| Ctrl+Shift+Up / Ctrl+Shift+Down | Фокус на предыдущую / следующую панель сплита |
| Ctrl+Shift+Left / Ctrl+Shift+Right | Активировать предыдущий / следующий таб |
| Alt+F4 | Выход |
Всегда активны, не настраиваются через settings.json
| Клавиша | Контекст | Действие |
|---|---|---|
| Up / Down / Tab | любое открытое меню/список | Переместить выделение |
| Enter | любое открытое меню/список | Подтвердить выбор |
| Escape | любое открытое меню/список | Закрыть меню |
| Ctrl+= / Ctrl+- | глобально | Изменение размера шрифта (только на сессию) |
Табы
- Все табы живут в одной строке в заголовке окна — отдельной полосы табов под ним нет.
- Клик по
+открывает дефолтный профиль (tabs[0]); если настроено больше одного профиля, маленький выпадающий список рядом с+позволяет выбрать, какой открыть. - Полоса табов прокручивается горизонтально колесом мыши, если табов больше, чем помещается.
- Любое действие «новый таб» — кнопка
+, выпадающий список профилей, любая горячая клавиша — идёт через один и тот же код, поэтому поведение одинаково независимо от способа открытия.
Сплиты
- Каждый таб поддерживает до 3 уровней панелей сплита (главная панель + 3 сплита).
Ctrl+Shift+\разделяет текущую сфокусированную панель; направление чередуется вправо → вниз → вправо по мере продолжения разделения.Ctrl+Shift+Backspaceзакрывает последний созданный сплит и переключает фокус на соседнюю панель.Ctrl+Shift+Up/Ctrl+Shift+Downциклически переключают фокус между главной панелью и живыми сплитами.- Переключение с таба «паркует» его сплиты (убирает их из видимой раскладки, но запоминает размеры); возврат к табу восстанавливает их точно в том виде, в котором вы их оставили — это работает для каждого таба независимо.
- Работает и на табах с
tmux: true— каждая панель сплита получает свою независимую живучую сессию.
Сохранение сессии (db.json)
Som запоминает открытые табы, их раскладку сплитов, (для табов с tmux: true) ID их удалённых сессий и — когда window.mode = "windowed" — последнюю позицию и размер окна, всё в ~/.config/som/db.json. Перезапуск Som возвращает вас туда, где вы остановились, включая переподключение к всё ещё работающим удалённым шеллам вместо запуска новых.
Этот файл перезаписывается автоматически при каждом открытии/закрытии таба или сплита, переключении табов, изменении размера/перемещении окна или выходе — руками его трогать не нужно. Если он вдруг отсутствует или повреждён, Som просто откатывается к одному пустому табу (и позиции окна по умолчанию), а не отказывается запускаться.
Восстановление при запуске
При старте Som не ждёт медленных подключений, прежде чем показать окно:
- Каждый сохранённый таб появляется сразу как плейсхолдер (только имя и иконка), в том же порядке, в котором был в прошлый раз, с уже выбранным ранее активным табом.
- Реальный терминал/шелл каждого таба подключается в фоне, заменяя плейсхолдер, как только готов — медленный SSH-логин в одном табе не задерживает быстрый локальный шелл в другом.
- Заголовок окна показывает небольшой спиннер в зоне перетаскивания (пустое место рядом с полосой табов), пока хоть один таб ещё восстанавливается, подключается или проверяется на передеплой tmux — как только всё устаканивается, спиннер исчезает.
- Панели сплитов пересоздаются после того, как существуют все табы, а ранее сфокусированные таб и панель получают фокус последними.
somsrv: живучие удалённые сессии
Установка "tmux": true в профиле таба направляет терминал этого таба через небольшой сопутствующий процесс (somsrv) вместо обычного PTY:
- Локальные шеллы: отсоединённый процесс держит реальный шелл и PTY; он продолжает работать, даже если Som закрыт, так что повторное открытие Som переподключается к точно той же сессии (scrollback, запущенные программы — всё) вместо запуска заново.
- Удалённые шеллы (
ssh/wsl): тот же механизм работает и на удалённой стороне — Som разворачивает небольшой предсобранный бинарникsomsrvв~/.local/bin/на удалённом хосте (перекопируя его только если версия устарела), и удалённый шелл работает внутри него. Это значит, что нестабильное соединение или закрытие Som не убивает вашу удалённую сессию; переподключение подхватывает тот же шелл обратно. Сам предсобранный бинарник встроен внутрь Som (Windows/macOS/Linux amd64 — Linux arm64 пока не собирается, и профиль сtmux: true, указывающий на такой хост, откатывается к обычному, не живучему подключению с уведомлением, вместо отказа открыться). - Каждая панель с tmux-бэкендом получает свою собственную живучую сессию, идентифицируемую внутренне через UUID — это прозрачно для вас, но именно это сохраняется в
db.json, чтобы сделать переподключение возможным. - Som периодически подчищает заброшенные удалённые сессии (те, что больше не соответствуют ничему в вашем текущем списке табов) на одной и той же машине, чтобы устаревшие процессы не накапливались на хостах, к которым вы часто подключаетесь. Это делается по принципу best-effort: если по какой-то причине не получается, это логируется и игнорируется, не блокируя открытие таба.
- Разделение таба с tmux-бэкендом работает так же, как и с любым другим табом — каждая новая панель сплита получает свою независимую живучую сессию (свой pane_id), а не общую.
У этой фичи нет отдельного переключателя в settings.json помимо "tmux": true на уровне профиля — глобального включения/выключения нет.
Картинки в терминале (Som Rich Protocol)
Som реализует собственный бинарный протокол для передачи насыщенного контента (пока изображения/GIF, аудио/markdown/видео зарезервированы на будущее) через PTY — утилита somcat, идущая вместе с Som, служит эталонным клиентом: somcat some.gif передаёт файл и показывает его прямо в терминале. Отдельного переключателя в settings.json для этого нет: функция всегда включена.
- Изображения — это настоящий текст сетки. Каждое переданное изображение становится блоком Unicode-плейсхолдер-ячеек, напечатанных прямо в scrollback терминала, поэтому обычная обработка скролла/очистки/истории самим терминалом корректно позиционирует и прячет картинку без какого-либо специального кода — очистка экрана прячет картинку, а скролл двигает её точно как любую другую строку вывода.
- Изображения сохраняют пропорции. Som вписывает декодированное изображение в переданный отправителем прямоугольник ячеек сетки, а не растягивает его на всю область.
- Изображения переживают переподключение SSH на табах с
tmux: true. Переподключение к сессииsomsrv, в которой на экране были картинки, перерисовывает их вместе с остальным содержимым scrollback, без ручного обновления. - Рендеринг идёт через тот же GPU-конвейер, что и текст — нет оверлейного окна, нет внешнего вспомогательного процесса. Изображения декодируются один раз и рисуются как любое другое содержимое GPUI.
Темы
Som поставляется с одной встроенной темой, «Nord Dark» (дефолт window.theme), записываемой в ~/.config/som/themes/nord.json при первом запуске. Базовый движок тем поддерживает произвольные файлы тем с примерно 150 индивидуально адресуемыми цветами, но Som пока не предоставляет отдельного способа установки дополнительных тем, кроме ручного размещения совместимого JSON-файла темы в директории тем и указания её имени в window.theme.
Поскольку формат тем Som — тот же самый, что использует сам Zed, любой JSON-файл темы Zed работает как есть. Несколько популярных:
Чтобы установить: скачайте JSON-файл темы в ~/.config/som/themes/, затем укажите в settings.json в поле window.theme значение поля "name" из самого файла (откройте файл и проверьте — оно не всегда совпадает с именем файла, а некоторые файлы описывают сразу несколько именованных вариантов).