From 99cedd2344c5d4eb30d03efe4af0400f8e3ee457 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Wed, 27 May 2026 16:35:34 +0600 Subject: [PATCH] [2026-05-27] doc: non-Steam binary VDF shortcuts guide --- .../how-to/htpc-steam-nonsteam-shortcuts.md | 95 +++++++++++++++++++ work/briefs/inbox/2026-05-27.md | 8 ++ 2 files changed, 103 insertions(+) create mode 100644 family/how-to/htpc-steam-nonsteam-shortcuts.md diff --git a/family/how-to/htpc-steam-nonsteam-shortcuts.md b/family/how-to/htpc-steam-nonsteam-shortcuts.md new file mode 100644 index 00000000..be4c9655 --- /dev/null +++ b/family/how-to/htpc-steam-nonsteam-shortcuts.md @@ -0,0 +1,95 @@ +# Non-Steam Shortcuts через Binary VDF + +## Формат файла + +Shortcuts хранятся в бинарном VDF: +`~/.steam/steam/userdata/147839491/config/shortcuts.vdf` + +**Это НЕ текстовый файл** — редактировать через обычную замену строк нельзя, потому что: +- Каждое поле хранится с длиной строки +- Замена строки на другую длины ломает весь файл +- Steam после запуска может перезаписать сломанный файл, удалив все non-Steam игры + +## Безопасный способ — Python + +```python +import os, struct + +vdf_path = os.path.expanduser('~/.steam/steam/userdata/147839491/config/shortcuts.vdf') + +# 1. Всегда делать бэкап +import shutil +shutil.copy2(vdf_path, vdf_path + '.bak') + +with open(vdf_path, 'rb') as f: + data = bytearray(f.read()) + +# Helper: string field +def sf(name, value): + nb = name.encode() + b'\x00' + vb = value.encode() + b'\x00' + return bytes([0x01, len(nb)]) + nb + bytes([len(vb)]) + vb + +# Helper: int field +def zf(name, value): + nb = name.encode() + b'\x00' + vb = struct.pack(' 2000000000 чтобы не конфликтовать с реальными Steam AppID) diff --git a/work/briefs/inbox/2026-05-27.md b/work/briefs/inbox/2026-05-27.md index 84a2d32f..ae8f322c 100644 --- a/work/briefs/inbox/2026-05-27.md +++ b/work/briefs/inbox/2026-05-27.md @@ -31,3 +31,11 @@ _Snapshot generated at 13:31 local (after SINCE 13:01). No task changes or comme Inbox quiet — nothing new. _No tasks modified since SINCE (Asana MCP: assigned + followed, both empty). No active meetings (MS365 clean). Alex AFK today (holiday)._ + +--- + +## Inbox Triage — 2026-05-27 15:32 (since 2026-05-27T16:01:02) + +Inbox quiet — nothing new. + +_No tasks modified since SINCE (Asana MCP: assigned + followed, both empty). No active meetings (MS365 clean). Alex AFK today (holiday). Not posting to #inbox per user directive._