[{"data":1,"prerenderedAt":135},["ShallowReactive",2],{"$fBBQ5ulyG5jVWbIBJe3r8F-kTKQKf1scMJiu0B6qzX5k":3,"$f7AVZHmPutZ23_8XKkLbDtEszKCuiY3yPjIDp9eRXGag":5,"$fYZO0gENG7R_6_vC_pV_tZO83B9kHqBn6kkXRMwGPTjg":7,"$fls2IKF-NukBDsCfImn6B10bonN1PFiQwGDvy41THzqM":111},{"data":4},[],{"data":6},[],{"data":8,"meta":107},[9],{"id":10,"documentId":11,"title":12,"seo_title":13,"summary":14,"seo_description":15,"slug":16,"published_date":17,"body":18,"content":19,"createdAt":38,"updatedAt":39,"publishedAt":40,"blogauthor":41,"cover":50,"categories":96},338,"d8x9in3uobdbi6ul45e37mhh","Skill of the week: Spring Explore — первичный сбор контекста","Spring Explore: skill для сбора контекста Spring-проекта","Стандартный Explore в Claude Code плохо разбирается в Spring. Рассказываем, как Spring Explore skill помогает агенту понять проект перед задачей.","Skill of the Week: Spring Explore собирает контекст Spring-приложения для AI-агента с учётом starters, OpenAPI и бинов. Установка и использование в своих skill.","skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta","2026-06-09","Первичное наполнение контекста — крайне важная задача, результаты которой влияют на качество решения\u002Fсгенерированного кода, возможно, даже больше, чем выбранная модель. В Claude Code за это отвечает Explore sub-agent, который, к слову, справляется неплохо, ровно до тех пор, пока вы не начинаете \"по настоящему\" использовать Spring: добавляя собственные starters, используя OpenAPI (Spec-first), определяя Bean\u002FComponents в стиле Josh Long (описывая их в конфигурациях), а также внедряя множество других инструментов фреймворка. В этом случае качественный анализ можно провести, только зная особенности работы Spring Framework и экосистемы.\n\nВ этом выпуске еженедельного дайджеста Skill of the week разберёмся, как, используя Spring Explore Skill, научить агента понимать специфику Spring-приложения и выполнять качественный первичный анализ.\n\n\u003Ch3 id=\"spring-explore\">Spring Explore\u003C\u002Fh3>\n\nSpring Explore — Skill, решающий задачу построения первичного контекста для поставленной вами задачи с учётом специфики Spring, Spring Boot, Spring Data JPA\u002FJDBC, Spring MVC и множества других компонентов, применяемых разработчиками при разработке приложений.\n\nКроме того, данный Skill включает не только поддержку фреймворков и библиотек, но также расширяет знания Agent в области понимания подходов проектирования и организации архитектуры приложения.\n\n\u003Ch3 id=\"kak-ustanovit\">Как установить\u003C\u002Fh3>\n\nУстановить Spring Skills глобально во все обнаруженные агенты:\n\n```bash\nnpx skills add Amplicode\u002Fspring-skills -g\n```\n\nУстановить только для конкретных агентов (пример — Claude Code + Codex + Gemini CLI):\n\n```bash\nnpx skills add Amplicode\u002Fspring-skills -g -a claude-code -a codex -a gemini-cli\n```\n\nС более подробной инструкцией можно ознакомиться [тут](https:\u002F\u002Famplicode.ru\u002Fdocumentation\u002Fspring-agent\u002F).\n\n\u003Ch3 id=\"ruchnoe-ispolzovanie\">Ручное использование\u003C\u002Fh3>\n\nДля начала разберёмся, как воспользоваться скилом в \"ручном\" режиме, непосредственно указывая agent на его использование. Нужно это в ситуации, когда вы хотите получить ответ на некоторый вопрос (выяснить, как что-то работает в приложении) или же когда явным образом хотите определить цель исследования.\n\nПопробуем собрать контекст для задачи, приближенной к реальной: [issue в spring-petclinic](https:\u002F\u002Fgithub.com\u002Fikuchmin\u002Fspring-petclinic\u002Fblob\u002Fa042df718468d542fa662f9c99a1b2e0db8b1f74\u002Fdocs\u002Fissues\u002F001-vet-work-schedule.md).\n\n> Краткое описание:\n>\n> Управление рабочими расписаниями ветеринаров — функциональность, позволяющая администратору клиники создавать и управлять рабочими графиками ветеринаров: задавать именованные расписания со сменами (дата, время начала и окончания), отмечать одно из расписаний как активное для записи, а также автоматически проверять при создании визита, что выбранный ветеринар работает в указанное время и не занят другим приёмом.\n\n\u003Cvideo src=\"https:\u002F\u002Fstorage.yandexcloud.net\u002Famplicode-site\u002Farticles\u002Fanatomiya_claude_code_pervichnyy_analiz_i_napolnenie_konteksta\u002Fspring_explore_with_mcp.mp4\" controls muted loop playsinline width=\"100%\" poster=\"{{strapiUrl}}\u002Fuploads\u002Fcover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp\" preload=\"none\">\u003C\u002Fvideo>\n\nКак видно на видео, skill используется явно `\u002Fspring-explore ...`, а значит, agent активирует его в первую очередь.\n\n\u003Ch3 id=\"avtomaticheskoe-ispolzovanie\">Автоматическое использование\u003C\u002Fh3>\n\nClaude Code, Codex и другие agent умеют самостоятельно подбирать и активировать необходимые для задачи skills. Повлиять на это авторы skill могут опосредованно, описав функциональность и возможные паттерны использования в description SKILL.md. Естественно, это не может гарантировать, что skill будет вызван именно для вашей задачи — на этом можно только надеяться.\n\n\u003Cvideo src=\"https:\u002F\u002Fstorage.yandexcloud.net\u002Famplicode-site\u002Farticles\u002Fsow-spring-explore\u002Fauto_activate.mp4\" controls muted loop playsinline width=\"100%\" poster=\"{{strapiUrl}}\u002Fuploads\u002Fcover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp\" preload=\"none\">\u003C\u002Fvideo>\n\n\u003Ch3 id=\"ispolzovanie-v-sobstvennyh-skill-i-agentah\">Использование в собственных skill и агентах\u003C\u002Fh3>\n\nSpring Explore также хорошо использовать в собственных skill — в ситуации, когда skill'у требуется провести некоторый анализ, на основе которого будут приняты решения о том, какой следующий шаг или же в каком виде нужно сгенерировать код.\n\nВ качестве примера рассмотрим разработку skill, задача которого — создание новых REST endpoint в нашем приложении. Однако есть одно условие: так как наше приложение полагается на DDD, то и пути в endpoint также должны соответствовать данной логике. Это значит, что на верхнем уровне request path у нас должны присутствовать только aggregate root.\n\nПо большому счёту такой skill будет состоять из двух шагов:\n\n- определение параметров (request path, http method, ...)\n- реализация endpoint в контроллере\n\nДля определения request path нам нужно представление модели в проекции DDD, эту задачу мы как раз и решим с помощью spring-explore.\n\nНазовём наш skill `rest-endpoint-ddd`\n\n````markdown\n---\nname: rest-endpoint-ddd\ndescription: >\n  Adds a REST endpoint to a Spring Boot project.\n  Use this whenever the user wants to add, create, expose, or design a REST endpoint, API\n  route, HTTP handler, or web resource — e.g. \"add an endpoint to list an order's line items\",\n  \"expose customers as JSON\", \"create a GET for articles by tag\" — even if they don't say\n  the word \"REST\".\n---\n\n# Add a REST Endpoint (DDD-driven)\n\n## Step 1 — Design the request contract\n\nProduce a precise contract to hand to step 2:\n\n```\nMETHOD  PATH                                params      →  RESPONSE\nGET     \u002Forders\u002F{orderId}\u002Fitems             page, size  →  List\u003CItemDto>\n```\n\n### 1a — Explore the domain and the controllers\n\nInvoke the **spring-explore** skill — `Skill(spring-explore)` — and tell it what you need:\n\n- **DDD aggregate model** for the entities in the task (required) — returns the aggregate tree\n  (`[root]` \u002F `[member]` \u002F `→ ref:`) that the path is derived from.\n- **Existing controllers** for those entities (its \"Get entity controllers\" path) — so you know\n  whether a controller already owns this resource area.\n- Entity descriptions \u002F DTOs \u002F repositories as needed to shape the response and confirm the\n  data is reachable.\n\nIf this context was already gathered earlier in the conversation, reuse it.\n\n### 1b — Derive the path from the aggregate tree\n\n- **Aggregate root → top-level collection.** `Order [root]` → `\u002Forders`, `\u002Forders\u002F{orderId}`.\n- **Member → nested under its root.** A `[member]` is never addressed alone. `Item [member]`\n  under `Order` → `\u002Forders\u002F{orderId}\u002Fitems\u002F{itemId}`; members of members nest further:\n  `Note` under `Item` → `\u002Forders\u002F{orderId}\u002Fitems\u002F{itemId}\u002Fnotes`.\n- **Cross-aggregate reference (`→ ref:`) → query\u002Ffilter param, never a nesting segment.** The\n  referenced root does not own the entity. Orders filtered by customer is `\u002Forders?customerId=…`,\n  not `\u002Fcustomers\u002F{id}\u002Forders`.\n\nMethod follows intent: read → `GET`, create → `POST`, replace → `PUT`, partial → `PATCH`,\nremove → `DELETE`. A trailing `{id}` marks single-item vs. collection.\n\n### 1c — Decide where it lives and what it returns\n\n- **Controller.** Prefer the controller that already owns this resource area (an items endpoint\n  joins `OrderController` if it exists). Create a new one only if none fits, matching neighbours'\n  package and class style.\n- **Response.** Carry member data inline; carry cross-aggregate references as **IDs only**\n  (`productId`, not a nested `Product`) — this is what keeps the payload aligned with aggregate\n  boundaries instead of leaking unrelated roots.\n\n---\n\n## Step 2 — Implement\n\nOnce the contract from step 1 is in hand, **proceed directly to implementation** — do not stop\nto present the design and wait for approval. The contract is the input to this step, not a\ndeliverable to hand back; designing without building leaves the task unfinished. Continue\nstraight into the work below.\n\nBuild the contract in the idiom of this project — the exploration already showed how existing\ncontrollers, DTOs, and repositories are written; match them, and read a neighbour first if a\nconvention is unclear (annotations, constructor injection, return-body style, naming). Add no\nlayers, frameworks, or patterns the project doesn't already use.\n\nBuild only what the contract requires, in dependency order:\n\n1. **Repository method** — add a derived query (or `@Query`) only if the data isn't already\n   reachable; reuse what's there first.\n2. **DTO(s)** — add a dedicated shape only if the response\u002Frequest needs one. Cross-aggregate\n   refs are IDs only.\n3. **Handler** — add it to the controller chosen in 1c. Map the path, bind params\n   (`@PathVariable`, `@RequestParam`, `@RequestBody`), call the repository\u002Fservice, return the\n   response in the project's body convention (e.g. `@ResponseBody` \u002F `@RestController`).\n4. **Wiring** — constructor-inject any new dependency the way neighbours do.\n\nAfterwards, confirm the result against the step-1 contract (method, path, params, response) to\ncatch drift.\n````\n\nДля проверки работоспособности нового skill добавим в проект сущности, связанные с расписанием ветеринара, в качестве aggregate member для сущности Vet.\n\n![]({{strapiUrl}}\u002Fuploads\u002F46574fefe79fe9ed56519382c9f81bd1_493be14903.webp)\n\nПосле чего воспользуемся новым skill для добавления REST endpoint на получение всех расписаний ветеринара.\n\n\u003Cvideo src=\"https:\u002F\u002Fstorage.yandexcloud.net\u002Famplicode-site\u002Farticles\u002Fsow-spring-explore\u002Fddd-rest-endpoint.mp4\" controls muted loop playsinline width=\"100%\" poster=\"{{strapiUrl}}\u002Fuploads\u002Fcover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp\" preload=\"none\">\u003C\u002Fvideo>\n\nЕсли тебе интересно, как настроить свой Agent для разработки на Spring, а также ты не хочешь пропустить новые выпуски Skill of the week и другие полезные материалы по разработке на Spring с AI Agent — подписывайся на канал в [ТГК](https:\u002F\u002Ft.me\u002Famplicode).\n\n---\n\n_Впервые опубликовано на [Хабре](https:\u002F\u002Fhabr.com\u002Fru\u002Fcompanies\u002Fhaulmont\u002Farticles\u002F1041314\u002F)._\n",[20],{"title":21,"links":22},"Содержание",[23,26,29,32,35],{"label":24,"href":25},"Spring Explore","#spring-explore",{"label":27,"href":28},"Как установить","#kak-ustanovit",{"label":30,"href":31},"Ручное использование","#ruchnoe-ispolzovanie",{"label":33,"href":34},"Автоматическое использование","#avtomaticheskoe-ispolzovanie",{"label":36,"href":37},"Использование в собственных skill и агентах","#ispolzovanie-v-sobstvennyh-skill-i-agentah","2026-11-12T11:24:41.598Z","2026-11-13T11:49:17.024Z","2026-11-13T11:49:17.078Z",{"id":42,"documentId":43,"firstname":44,"lastname":45,"createdAt":46,"updatedAt":46,"publishedAt":47,"slug":48,"photo":49},32,"o6vt7fwz9hd363ulcgbilr84","Илья","Кучмин","2026-11-12T11:20:31.602Z","2026-11-12T11:20:50.815Z","ilya-kuchmin",null,{"id":51,"documentId":52,"name":53,"alternativeText":49,"caption":49,"width":54,"height":55,"formats":56,"hash":91,"ext":60,"mime":61,"size":92,"url":93,"previewUrl":49,"provider":94,"provider_metadata":49,"createdAt":95,"updatedAt":95,"publishedAt":95,"focalPoint":49},1251,"w0wigt6rsrnisu2xvk763z94","cover-skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta.webp",1280,720,{"thumbnail":57,"large":67,"medium":75,"small":83},{"name":58,"hash":59,"ext":60,"mime":61,"path":49,"width":62,"height":63,"size":64,"sizeInBytes":65,"url":66},"thumbnail_cover-skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta.webp","thumbnail_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284",".webp","image\u002Fwebp",245,138,9.07,9066,"\u002Fuploads\u002Fthumbnail_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp",{"name":68,"hash":69,"ext":60,"mime":61,"path":49,"width":70,"height":71,"size":72,"sizeInBytes":73,"url":74},"large_cover-skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta.webp","large_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284",1000,562,38.22,38220,"\u002Fuploads\u002Flarge_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp",{"name":76,"hash":77,"ext":60,"mime":61,"path":49,"width":78,"height":79,"size":80,"sizeInBytes":81,"url":82},"medium_cover-skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta.webp","medium_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284",750,422,29.07,29074,"\u002Fuploads\u002Fmedium_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp",{"name":84,"hash":85,"ext":60,"mime":61,"path":49,"width":86,"height":87,"size":88,"sizeInBytes":89,"url":90},"small_cover-skill-of-the-week-spring-explore-pervichnyj-sbor-konteksta.webp","small_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284",500,281,18.95,18954,"\u002Fuploads\u002Fsmall_cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp","cover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284",55.36,"\u002Fuploads\u002Fcover_skill_of_the_week_spring_explore_pervichnyj_sbor_konteksta_2c803f6284.webp","local","2026-11-13T11:44:47.091Z",[97],{"id":98,"documentId":99,"title":100,"published":101,"weight":102,"slug":103,"createdAt":104,"updatedAt":105,"publishedAt":106,"color":49},4,"ap54riuwcv7sj63auhmb4i6d","Гайды",true,3,"guides","2026-11-12T11:20:31.298Z","2026-11-12T11:22:44.141Z","2026-11-12T11:22:44.122Z",{"pagination":108},{"page":109,"pageSize":110,"pageCount":109,"total":109},1,25,{"data":112,"meta":131},[113,119,125],{"published_date":114,"id":115,"documentId":116,"title":117,"slug":118},"2026-09-28",327,"lruxexelyn19uak89r6dney5","Что такое OpenSpec? Полный гайд по Spec-Driven Development","chto-takoe-openspec-polnyj-gajd-po-spec-driven-development",{"published_date":120,"id":121,"documentId":122,"title":123,"slug":124},"2026-09-10",326,"ymtfa6pslevvkrwnohdfbi1u","Как не потерять интеграцию с Docker в IDE после блокировки JetBrains","kak-ne-poteryat-integracziyu-s-docker-v-ide-posle-blokirovki-jetbrains",{"published_date":126,"id":127,"documentId":128,"title":129,"slug":130},"2026-09-01",400,"dskd9jsck2vjm1d0ztoz91uo","JavaScript и TypeScript в OpenIDE: Node.js, React, Angular, Git и работа с API","javascript-i-typescript-v-openide",{"pagination":132},{"page":109,"pageSize":102,"pageCount":133,"total":134},6,16,1794584599880]