У світі інструментів для розробників рідко трапляються моменти, коли команда свідомо видаляє 15 тисяч рядків працюючого коду й замінює їх на кількасот рядків тексту у Markdown. Саме це зробив Cursor — AI-редактор коду, відомий своїми агентами та глибокою інтеграцією з Git. Співзасновник і технічний лідер Cursor Девід Гомеш розповів, як команда спочатку побудувала складну нативну реалізацію Git work trees і режиму Best-of-N, а потім повністю викинула її й відтворила ту саму поведінку як набір «скилів» і субагентів, описаних у Markdown-промптах.
![]()
Ця історія — не лише про оптимізацію коду. Вона показує, як змінюється саме поняття «функції продукту», коли значна частина логіки переноситься з класичного застосункового коду в промпти, що керують поведінкою моделей.
Важка артилерія Cursor 2.0: work trees і Best-of-N як нативна фіча
Щоб зрозуміти масштаб змін, варто повернутися до жовтня 2023 року, коли разом із Cursor 2.0 з’явилися дві ключові можливості: Git work trees та режим Best-of-N. Вони були реалізовані як повноцінна нативна фіча всередині застосунку.
Git work trees у Cursor — це, по суті, паралельні checkout-и репозиторію. Кожен work tree — окреме робоче дерево, в якому агент може змінювати код, запускати команди, лінтери й тести, не торкаючись основної гілки розробника. На екрані це виглядало як сітка агентів, що одночасно працюють над різними задачами або навіть над однією задачею, але в різних варіантах.
Ключова ідея: один і той самий файл міг існувати в кількох work trees з різним вмістом. Агент змінював файл у своєму ізольованому дереві, а основний checkout залишався недоторканим, доки користувач не вирішував застосувати зміни або відкрити pull request саме з цього work tree.
На цьому фундаменті Cursor побудував Best-of-N — режим, у якому одна й та сама задача віддається кільком моделям одночасно. Кожна модель працює у власному work tree, генерує свою реалізацію, а користувач може:
- порівняти різні варіанти коду;
- подивитися візуальні відмінності у фронтенд-проєктах;
- обрати найкращу реалізацію.
Цей режим перетворював вибір моделі з абстрактного налаштування в реальний експеримент: різні моделі «змагалися» на одному й тому самому завданні.
Ціна такої потужності була високою. Початкова реалізація work trees і Best-of-N складалася приблизно з 15 000 рядків коду. Вона включала:
- створення й менеджмент work trees;
- підключення їх як контексту для агентів;
- жорстку ізоляцію, щоб модель фізично не могла торкатися файлів поза своїм work tree;
- підтримку користувацьких setup-скриптів, які запускалися при старті агента в конкретному work tree;
- систему «судді», що оцінювала результати різних моделей і підсвічувала найкращу реалізацію;
- зміни в «harness» та системні нагадування, які допомагали агенту «пам’ятати», що він працює в конкретному work tree;
- складну логіку прибирання, щоб не дозволити користувачам ненавмисно створювати сотні work trees і забивати диск.
Це була класична інженерна історія: потужна, глибоко інтегрована, але важка у підтримці фіча з великою кількістю залежностей і тестів.
Велике видалення: мінус 15 000 рядків і перехід до Markdown-скілів
Наступний крок виглядає радикально навіть за мірками швидкого AI-розвитку. Cursor відкрив pull request, у якому повністю видалив нативну реалізацію work trees. Застосунок втратив близько 15 тисяч рядків коду — ціла підсистема зникла.
На її місці з’явився інший підхід: замість того, щоб реалізовувати поведінку work trees і Best-of-N у вигляді класичного застосункового коду, команда перенесла логіку в промпти — так звані «скили» та субагенти, описані у Markdown.
Це означало кілька принципових змін.
По-перше, сама поведінка фічі перестала бути жорстко прошитою в клієнт. Замість цього вона стала результатом інструкцій, які отримує модель: як створювати work tree, як у ньому працювати, як запускати скрипти, як не виходити за межі цього дерева.
По-друге, розмір реалізації скоротився на порядки. Якщо попередня версія Best-of-N займала близько 4 000 рядків коду, то новий Best-of-N-скіл вміщується приблизно в 40 рядках Markdown. Разом із новим скілом для work trees загальний обсяг — «порядку кількох сотень рядків» Markdown, які замінюють 12–15 тисяч рядків нативної системи.
По-третє, ці скіли стали частиною сервер-контрольованих команд. Промпти, які описують поведінку work trees і Best-of-N, живуть на бекенді Cursor. Їх можна змінювати, не випускаючи нову версію клієнта. Коли користувач наступного разу викликає відповідну команду, він автоматично отримує оновлену логіку.
Фактично Cursor перетворив частину свого продукту з «коду як артефакту» на «код як текстову специфікацію для моделі».
Як працює новий шар: скіли, субагенти й 40 рядків Markdown
Новий підхід спирається на два вже існуючі примітиви Cursor: скіли агентів і субагенти. Скіл — це, по суті, промптова інструкція, яка описує, як агент має поводитися в певному сценарії. Субагенти — це дочірні агенти, які можуть працювати паралельно, кожен зі своїм контекстом і, за потреби, своєю моделлю.
Команда зрозуміла, що, комбінуючи ці два механізми, можна відтворити і поведінку work trees, і Best-of-N без важкої нативної реалізації.
Новий скіл для work trees описує кілька ключових речей:
- як створити Git work tree;
- як запустити користувацькі setup-скрипти, якщо вони налаштовані;
- як працювати всередині цього checkout-а;
- як не виходити за його межі.
Це — текстові інструкції для моделі, написані у Markdown. Вони враховують кросплатформеність: окремі вказівки для Windows, Linux і macOS. Модель отримує чіткі кроки, які команди запускати й у якому середовищі.
Best-of-N реалізовано як окремий скіл, ще компактніший. Приблизно 40 рядків Markdown описують сценарій, у якому:
- «батьківський» агент створює субагента для кожної моделі, яку вказав користувач;
- кожен субагент створює власний work tree й працює тільки в ньому;
- батьківський агент чекає завершення всіх субагентів;
- після цього він аналізує результати, порівнює реалізації, може їх оцінити, покритикувати й допомогти користувачу обрати найкращу;
- за потреби батьківський агент формує зведену відповідь, наприклад у вигляді таблиці.
Те, що раніше вимагало тисяч рядків коду, тепер описано як сценарій поведінки моделі. Важливий нюанс: хоча це виглядає як «код», технічно це Markdown — текст, який інтерпретує не компілятор, а LLM.
Окремий блок інструкцій присвячений найскладнішій частині — утримати модель у межах потрібного work tree. Якщо раніше ізоляція забезпечувалася на рівні системи (модель фізично не могла торкнутися файлів поза своїм деревом), то тепер це досягається «агресивним промптингом»: багаторазовими й чіткими вказівками ніколи не працювати поза заданим checkout-ом і не «тікати» з нього.
Команди замість UI: /worktree, /bestevent і сервер-контрольовані промпти
Разом із переходом на скіли змінився й спосіб взаємодії користувача з work trees і Best-of-N. Якщо раніше це була частина UI з випадаючими списками та налаштуваннями, то тепер усе зведено до slash-команд.
Основні нові команди:
/worktree— створює ізольований work tree для задачі, яку формулює користувач. Наприклад, можна написати/worktree fix a typo in the footer of the website, і агент виконає цю правку у власному work tree, не торкаючись основного checkout-а./bestevent— запускає режим Best-of-N, коли одна й та сама задача віддається кільком моделям, кожна у своєму work tree.
Додатково з’явилися:
apply_worktree— переносить зміни з побічного work tree в основний checkout;delete_worktree— видаляє work tree й очищує сліди його роботи.
Формально ці механізми в Cursor оформлені не як скіли, а як команди. Однак внутрішньо вони працюють дуже схоже: відповідні промпти підвантажуються в контекст моделі лише тоді, коли користувач викликає команду.
Ключова відмінність у тому, де живуть ці промпти. Вони зберігаються й керуються на сервері Cursor. Це дає кілька важливих наслідків.
По-перше, команда може ітеруватися над промптами без оновлення клієнта. Якщо інженери покращують інструкції для моделі — наприклад, уточнюють, як поводитися в багаторепозиторних проєктах або як надійніше залишатися в межах work tree, — користувачі отримують ці зміни автоматично при наступному виклику команди.
По-друге, це відкриває шлях до систематичного тюнінгу поведінки через експерименти з промптами, не торкаючись основного коду застосунку. Логіка фічі стає гнучкішою й менш «зашитою» в релізний цикл.
З точки зору користувача, новий підхід має ще одну практичну перевагу: тепер можна переключитися в work tree посеред розмови з агентом. Раніше UI не дозволяв елегантно додати таку опцію, не перевантажуючи інтерфейс. Тепер достатньо в будь-який момент ввести /worktree з описом задачі — і агент продовжить роботу вже в ізольованому дереві.
Нові можливості: мульти-репо, гнучкі Best-of-N і менше техборгу
Перехід до скілів у Markdown не лише спростив підтримку, а й відкрив кілька можливостей, яких не було в попередній нативній реалізації.
Одна з них — повноцінна підтримка мульти-репо-сетапів. У багатьох команд фронтенд і бекенд живуть у різних репозиторіях. У старій системі work trees в такому сценарії просто не працювали: фіча була відключена для багаторепозиторних проєктів.
Новий /worktree поводиться інакше. Якщо користувач працює з кількома репозиторіями одночасно, агент створює окремий work tree для кожного з них. Коли користувач просить відкрити pull request, система формує кілька PR-ів — по одному на кожен репозиторій. Таким чином, паралельна робота з фронтендом і бекендом у рамках однієї задачі стає прозорою.
Ще одна суттєва зміна стосується Best-of-N. У новій реалізації батьківський агент має значно більше контексту про те, що зробив кожен субагент у своєму work tree. Це дозволяє не лише «вказати переможця», а й:
- детально описати відмінності між реалізаціями;
- сформулювати критику й оцінки;
- допомогти користувачу зрозуміти сильні й слабкі сторони кожного варіанту;
- за запитом користувача «зшити» найкращі частини з різних реалізацій в один комбінований варіант.
У попередній системі користувачеві доводилося обирати один субагент або одну модель і далі працювати тільки з нею. Тепер Best-of-N перетворюється на більш інтерактивний процес, де батьківський агент виступає своєрідним фасилітатором, який допомагає комбінувати ідеї.
З інженерної точки зору головний плюс очевидний: обсяг коду, який потрібно підтримувати, різко скоротився. Work trees — це фіча для «паверкористувачів», а не для 90% аудиторії Cursor. Тримати для неї окрему складну нативну підсистему з тисячами рядків коду означало постійний технічний борг. Перенесення логіки в кількасот рядків Markdown знімає значну частину цього навантаження.
Ціна гнучкості: коли ізоляція тримається на промптах
Втім, новий підхід не обійшовся без компромісів. Найбільша втрата порівняно з попередньою реалізацією — це жорстка технічна ізоляція work trees.
У старій системі модель фізично не могла торкнутися файлів поза своїм work tree. Інфраструктура просто не давала їй такої можливості. Це гарантувало, що жодна дія агента не зачепить основний checkout, поки користувач сам не вирішить застосувати зміни.
Тепер Cursor «довіряє» моделі. Ізоляція забезпечується не системними обмеженнями, а промптами. Модель багаторазово й наполегливо просять:
- працювати тільки в межах конкретного work tree;
- не змінювати файли в основному checkout-і;
- не «втекти» з виділеного середовища.
Це робить поведінку більш крихкою. Моделі різних розмірів і архітектур можуть по-різному реагувати на інструкції. Деякі будуть дисципліновано дотримуватися промптів, інші — час від часу «забуватимуть» про обмеження й торкатимуться основного репозиторію.
Cursor уже бачить змішаний фідбек від користувачів щодо нового підходу до work trees. Частина аудиторії звикла до старого UI й попередньої моделі взаємодії, частина — до гарантій жорсткої ізоляції. Новий варіант дає більше гнучкості, але водночас покладається на поведінку моделей, яку складніше формально гарантувати.
Команда не приховує цих недоліків і сприймає їх як зону для подальшої роботи. Водночас курс на «Markdown як код» залишається: навіть із цими ризиками вигода від зменшення складності й можливість швидко еволюціонувати промпти виявилися достатньо вагомими, щоб піти на радикальний рефакторинг.
Висновок: коли продуктова логіка переїжджає з коду в промпти
Історія work trees і Best-of-N у Cursor — це концентрований приклад того, як змінюється інженерна практика в епоху LLM. Те, що ще рік тому здавалося «нормальним» — тисячі рядків нативного коду, складна інфраструктура, жорстка ізоляція на рівні системи, — сьогодні може бути замінено кількома сотнями рядків Markdown, які описують поведінку моделі.
Цей перехід має кілька вимірів.
По-перше, змінюється роль коду. Частина того, що раніше реалізовувалося як алгоритми й структури даних, тепер стає текстовою специфікацією для моделі. Інженер пише не лише функції, а й інструкції, які мають бути зрозумілими для LLM.
По-друге, змінюється життєвий цикл фіч. Якщо логіка живе в промптах на сервері, її можна оновлювати й експериментувати з нею значно швидше, ніж із класичним застосунковим кодом, який вимагає релізів клієнта.
По-третє, змінюється баланс між гарантіями й гнучкістю. Жорстка ізоляція на рівні системи дає сильні гарантії, але коштує дорого в розробці й підтримці. Промптова ізоляція дешевша й гнучкіша, але менш формально надійна й потребує постійного тюнінгу.
Cursor зробив ставку на те, що в довгостроковій перспективі виграє саме гнучкість: менше нативного коду, більше поведінки, описаної в Markdown-скілі. Історія з видаленням 15 000 рядків і заміною їх на кількасот рядків промптів показує, що для AI-орієнтованих інструментів це вже не теоретичний експеримент, а практична інженерна стратегія.


