YouTube2Text

Как контролировать код ИИ-агентов: Quality Gates, архитектура и инструменты разработчика — Transcript

by Организованное программирование | Кирилл Мокевнин · 13,481 words · 2,105 segments · language en · Watch on YouTube

Full transcript

  1. 0:00Hello, friends. This is the Organized
  2. 0:02Programming podcast. I’m your host,
  3. 0:04Kirill Makevnin. I’ll be on my own today
  4. 0:07. And today's topic is Quality Gates and
  5. 0:11developer tools.
  6. 0:14If you follow my Telegram channel, you
  7. 0:17know I recently wrote a few posts on
  8. 0:20this topic, explaining how we are
  9. 0:23expanding our use of various linters—
  10. 0:25tools that not only check code against
  11. 0:28pre-set rules, but go a bit further,
  12. 0:31because we want agents to check more
  13. 0:34than just basic things in standard code
  14. 0:36, but also architectural rules and
  15. 0:39deeper concepts in general.
  16. 0:43And since I am currently working on
  17. 0:45another project alongside Hexlet—an
  18. 0:48entirely separate direction and business
  19. 0:50—we are launching an international
  20. 0:53marketing platform.
  21. 0:54It’s an open-source thing, a so-called
  22. 0:57OpenCore product. I’ve started showing
  23. 0:59it off quite a bit. Some people have
  24. 1:01already subscribed and are keeping an
  25. 1:03eye on it.
  26. 1:04I highly recommend doing that because
  27. 1:05it’s a product being built according to
  28. 1:07all the approaches and rules of modern
  29. 1:08AI-assisted development.
  30. 1:11It is literally one step away from
  31. 1:13release, from starting to sell it, and
  32. 1:15from actual implementation. So, this is
  33. 1:17a separate business of mine that you’ll
  34. 1:19be able to follow. You know how people
  35. 1:21say, "Go start a business and get rich.
  36. 1:23" Well, this is exactly that. It's a B2B
  37. 1:26SaaS that I’m building for specific
  38. 1:28reasons. This is a long-standing story;
  39. 1:30I’ve wanted to do it for a long time,
  40. 1:31but I didn't have the opportunity, time
  41. 1:33, or team. Now, AI really makes it
  42. 1:35possible. But it’s not a story—for those
  43. 1:37who watched previous episodes—about just
  44. 1:39slapping some code together and having
  45. 1:41it work. It’s clear that the main part
  46. 1:43is actually something else entirely. The
  47. 1:45product itself is straightforward, and
  48. 1:46it’s not that hard to build these days,
  49. 1:48especially if you know what to build.
  50. 1:50But implementation, sales, and
  51. 1:51understanding the market—that’s a
  52. 1:52completely different story. Far fewer
  53. 1:53people understand how that works and
  54. 1:55what needs to be done for it. But we
  55. 1:57happen to know a little bit about that.
  56. 1:59So you will be able to see firsthand how
  57. 2:01a product emerges from nothing and what
  58. 2:04its future fate will be. Accordingly, I
  59. 2:06will be reporting on it periodically.
  60. 2:08At least until we...you know how it
  61. 2:10often happens: people start a new
  62. 2:11project, they share and tell stories,
  63. 2:13but then, when it turns into a regular
  64. 2:15business and there’s a team and everyone
  65. 2:17is working, the founders just have a ton
  66. 2:18of other problems, and they aren't as
  67. 2:20interested in sharing anymore.
  68. 2:22And if at some point I stop talking
  69. 2:24about it, there will be two
  70. 2:25possibilities. Either nothing worked out
  71. 2:27, which I really wouldn't want, or quite
  72. 2:28the opposite, everything is good and
  73. 2:30we’ve simply entered normal business
  74. 2:31mode. I’ll probably just be approaching
  75. 2:33it from a different angle, I promise.
  76. 2:35But in any case, I will tell you about
  77. 2:36it, and you’ll be able to follow
  78. 2:38everything more or less in real-time.
  79. 2:40Why is it specifically related to that?
  80. 2:42Because, firstly, it's built using
  81. 2:44different technologies. It mainly uses
  82. 2:46Go.
  83. 2:48And since we were building this project
  84. 2:50according to certain principles from the
  85. 2:52start, plus Go is missing some things I
  86. 2:54need, I had to dig into this issue quite
  87. 2:56deeply to upgrade some technical aspects
  88. 2:58, which I’ll talk about today.
  89. 3:01So, that’s why today we’re talking a bit
  90. 3:04about developer tools, necessary for any
  91. 3:06base, related to things like hooks,
  92. 3:08setup, task execution, and so on, up to
  93. 3:11architecture checks.
  94. 3:13Basically, that’s our topic for today.
  95. 3:15So, let’s get started.
  96. 3:23I think the first thing I want to start
  97. 3:25with is auto-generation. There’s this
  98. 3:27belief with AIs that we can now generate
  99. 3:30anything we want.
  100. 3:31We don't need any libraries, we don't
  101. 3:33need frameworks, we can do everything
  102. 3:35from scratch, no problem at all.
  103. 3:37In reality, if you do that, there won’t
  104. 3:39just be a lot of code.
  105. 3:42First of all, it’s much harder to track
  106. 3:43boundaries, because, look, if you take a
  107. 3:45library, there’s a clear interface, it’s
  108. 3:47decoupled from you.
  109. 3:49If it’s done on the fly, and you don’t
  110. 3:52really check the code or watch what’s
  111. 3:54happening, it’s very easy for things
  112. 3:56that are usually separated, made
  113. 3:58independent, and isolated as modules to
  114. 4:00start blurring and mixing with the main
  115. 4:02logic.
  116. 4:03And there will be a lot, a lot, a lot of
  117. 4:04that.
  118. 4:05If you generate fast enough and add many
  119. 4:07features, reaching a point where you
  120. 4:09have a couple hundred thousand lines of
  121. 4:11code is absolutely trivial.
  122. 4:13It’s clear that with such a product, you
  123. 4:16won’t just deploy and release it easily
  124. 4:18. So it’s obvious that all of this still
  125. 4:21needs to be checked and you have to use
  126. 4:23your head, but there are still some
  127. 4:24basic principles that allow you to
  128. 4:26minimize the headache that will
  129. 4:28eventually arise from this generation.
  130. 4:30The first is understanding, in principle
  131. 4:32, what the system is built from, what it
  132. 4:33consists of, what elements there are,
  133. 4:35which elements can be extracted
  134. 4:36immediately, and which elements to use.
  135. 4:38For example, the first thing I used
  136. 4:40there and often talk about concerns
  137. 4:42generation.
  138. 4:43Instead of just taking raw Go, as people
  139. 4:45usually like to talk about—which, by the
  140. 4:48way, doesn't match what's happening on
  141. 4:50GitHub.
  142. 4:51There are tons of libraries on GitHub,
  143. 4:52and frameworks, and everything else. So
  144. 4:54, like, let's take raw Go and build
  145. 4:56everything from scratch.
  146. 4:58That’s certainly very fun and cool, but
  147. 5:00the thing is, a typical web project,
  148. 5:01well, a typical one—where there are lots
  149. 5:03of classic handlers, HTTP handlers, and
  150. 5:05so on.
  151. 5:06It could be an API, it could be a
  152. 5:08service. The thing I'm working on right
  153. 5:10now is a rather complex technical piece
  154. 5:11inside, with a bunch of different
  155. 5:13elements, like sending emails, and so on
  156. 5:14. And the concepts remain more or less
  157. 5:16the same. That is, you have handlers,
  158. 5:18there’s some business logic you need to
  159. 5:20call, there’s database interaction,
  160. 5:22there’s an API, you need to transform
  161. 5:24data, use some DTOs, and so on. Writing
  162. 5:27tests. In general, it’s an absolute
  163. 5:28classic for any web project, no matter
  164. 5:30what it’s doing. And in this whole mix
  165. 5:32of all these layers and all these
  166. 5:34stories that concern any web project,
  167. 5:36there are very clear parts, very clear
  168. 5:38approaches that should be used rather
  169. 5:40than neglected.
  170. 5:42So, the first is design-first; what are
  171. 5:44we talking about here?
  172. 5:45Design in this case refers to
  173. 5:47architectural design, not drawing
  174. 5:48pictures, because there is code-first
  175. 5:50and there is design-first. Code-first
  176. 5:52usually means we've knocked together
  177. 5:54some API, wrote documentation for it,
  178. 5:57threw it out to the frontend dev or
  179. 5:59whoever needed it at the time.
  180. 6:02It's clear that I'm doing all of this
  181. 6:03entirely by myself, from infrastructure
  182. 6:05to release, backend, frontend, and
  183. 6:06testing.
  184. 6:08There is no one else there. But even in
  185. 6:10this case, it’s important to think about
  186. 6:12how it will evolve from that perspective
  187. 6:13. And that's why I switched to a
  188. 6:15design-first approach, because it used
  189. 6:16to be difficult. You have to sit down,
  190. 6:18plan, design, you know, like the
  191. 6:19documentation, and then build something
  192. 6:21from that.
  193. 6:22And it was always very difficult,
  194. 6:24especially if you have a team, to get
  195. 6:26everyone to first change the API, the
  196. 6:28OpenAPI design, for example, and only
  197. 6:30then generate the corresponding elements
  198. 6:32that exist in the system.
  199. 6:34With CI, it became very simple, that is
  200. 6:37, practically effortless. Instead of
  201. 6:39building something right away, here is
  202. 6:40what I do first, there is a specific
  203. 6:42order to it. First, it’s not even the
  204. 6:44Open API that’s generated, but TypeSpec
  205. 6:46, which I also regularly talk about.
  206. 6:48It’s a language built on top of Open API
  207. 6:51that provides much better control
  208. 6:52guarantees. It’s more compact, more
  209. 6:54readable, and so on.
  210. 6:56It’s a really cool thing made by
  211. 6:58Microsoft, from which Open API is
  212. 6:59generated, and then, using ready-made
  213. 7:01tools—of which there are millions for
  214. 7:03frontend, backend, whatever you want—a
  215. 7:05literal ton of code is generated.
  216. 7:08I mean, not just a lot, but a whole lot
  217. 7:10of code. What does that include? Well,
  218. 7:12first of all, this thing immediately
  219. 7:14gives you an SDK for, say, Node. Well,
  220. 7:16basically, all SDKs in general.
  221. 7:18I mean, for example, clients for my
  222. 7:19platform here, they actually appear
  223. 7:20right out of the box simply because the
  224. 7:22generators exist.
  225. 7:23Furthermore, this thing fully generates
  226. 7:25frontend APIs for requests to the
  227. 7:27backend.
  228. 7:28Because when we talk about design-first
  229. 7:30, it’s not just about the external API.
  230. 7:33There are many different types of APIs.
  231. 7:34There’s an API for the site, an API for
  232. 7:36external users, and there could be other
  233. 7:38APIs too; in short, there are many kinds
  234. 7:39, and it generates all of them. So, some
  235. 7:41of these libraries are generated for
  236. 7:43external clients. And that means you
  237. 7:44don't have to write SDKs by hand at all
  238. 7:46. Everything is generated entirely from
  239. 7:48scratch. Whether you want it for Ruby,
  240. 7:50Go, Haskell, or any language like Rust—
  241. 7:52there you go, generated with zero human
  242. 7:55intervention. The second part is the
  243. 7:56generation, as I already mentioned, for
  244. 7:58frontend developers—or for the frontend
  245. 8:00in my case, because I’m building that
  246. 8:01too.
  247. 8:03In my setup, I use React Query, which
  248. 8:06effectively provides these abstractions
  249. 8:09related to my site.
  250. 8:11And then the UI uses that to perform the
  251. 8:14actual calls. This also saves a huge
  252. 8:16amount of code, resources, and attention
  253. 8:18when it’s all done, first of all,
  254. 8:20uniformly, and second, directly tied to
  255. 8:22this design.
  256. 8:24So the question of divergence doesn't
  257. 8:26even exist, because if the spec changes
  258. 8:28and then generation occurs, if something
  259. 8:29doesn't match in the types, it
  260. 8:31immediately makes itself known.
  261. 8:33It’s a very, very reliable thing. And
  262. 8:35one more important element.
  263. 8:38When I was choosing the Go approach, and
  264. 8:40specifically which coding style to pick
  265. 8:42, I was primarily looking not just at
  266. 8:44how popular an approach was, or how many
  267. 8:46pre-built middlewares there were, or
  268. 8:48even built-in test support—which is also
  269. 8:50quite important, because if the entire
  270. 8:52HTTP stack is loaded without options,
  271. 8:54like it was in Express, it's expensive,
  272. 8:56inconvenient, and creates a lot of
  273. 8:58various problems.
  274. 8:59I was also considering which of these
  275. 9:01approaches was most tailored for "
  276. 9:03design-first," meaning where the
  277. 9:05generators were.
  278. 9:06I think there were about four or five
  279. 9:08different frameworks I looked at.
  280. 9:10In the end, I found a library—well,
  281. 9:12there are two main ones that do the
  282. 9:14generation. One is more advanced, the
  283. 9:16other less so. I ended up choosing the
  284. 9:18one that is less popular, though it is
  285. 9:19still quite widely used. Ogen or
  286. 9:20something like that; I don't recall the
  287. 9:22exact name right now, but I'll provide
  288. 9:23it later. But the most important thing
  289. 9:24is that its level of generation is
  290. 9:25immense. It generates the incoming
  291. 9:27validation layer, the converters, and
  292. 9:29very importantly, all the handlers. It’s
  293. 9:32not just something that creates
  294. 9:34interfaces; it generates actual,
  295. 9:36specific handlers.
  296. 9:38All in all, it’s slightly worse than in
  297. 9:40Java, because in Spring Boot, for
  298. 9:42instance, you can generate a lot more,
  299. 9:44but it’s close to the ceiling of what is
  300. 9:46possible in Go regarding how much can be
  301. 9:49generated from that base design.
  302. 9:52In this podcast, I talk a lot about
  303. 9:53agentic development, Spec-Driven
  304. 9:55Development, and how the programmer's
  305. 9:57job is changing.
  306. 9:58But I don't just talk about it. Together
  307. 10:00with Prxsor, we are implementing these
  308. 10:02approaches in real engineering teams. We
  309. 10:04help transition from a situation where
  310. 10:06each developer uses Cursor or Cloud Code
  311. 10:07individually to a process where agents
  312. 10:09are integrated into the entire
  313. 10:11development cycle, from task definition
  314. 10:12to reviews, testing, and production. If
  315. 10:15you want to make this transition in your
  316. 10:16company, details are at prxsor.ru, link
  317. 10:18in the description. Just yesterday, as
  318. 10:21I'm currently running a program for
  319. 10:23programmers, I was giving a presentation
  320. 10:25to the guys, and I was showing what's
  321. 10:27happening using this project as an
  322. 10:29example. So, when I looked, it turned
  323. 10:31out that the project's codebase already
  324. 10:33has about 700,000 to 800,000 lines of
  325. 10:35code, of which, just so you understand,
  326. 10:37only 180,000 were written by hand. Well
  327. 10:40, he says "written by hand," but he
  328. 10:42means that's what the IDE wrote itself,
  329. 10:44rather than being generated by any other
  330. 10:46tools. Just think about that—more than
  331. 10:48500,000 lines of code were generated.
  332. 10:51It’s not just some trashy code, it’s
  333. 10:53that boilerplate code required for those
  334. 10:55hundreds of handlers, API endpoints,
  335. 10:57DTOs, converting data from the database
  336. 10:59into resources exposed externally, and
  337. 11:01so on and so forth.
  338. 11:02All of this is open; you can easily go
  339. 11:04in and take a look, and I believe that
  340. 11:06this approach is the future. Moreover, I
  341. 11:08am focusing on increasing the number of
  342. 11:10generators.
  343. 11:12That is, if I have some routine task
  344. 11:14where I need to generate something else
  345. 11:16, I don't ask the AI to write it for me
  346. 11:18in the first place.
  347. 11:20I first ask it, "Can this task be solved
  348. 11:22with an additional extension, for
  349. 11:24example, an emitter for TypeSpec?"
  350. 11:27Because you can write emitters for
  351. 11:28TypeSpec that can generate anything you
  352. 11:30need based on what is described in the
  353. 11:32TypeSpec.
  354. 11:33The same applies to OpenAPI, because
  355. 11:35there are also these generators for
  356. 11:37OpenAPI that are usually extensible,
  357. 11:38allowing you to write something to
  358. 11:40achieve the desired result.
  359. 11:42In other words, I ultimately try to
  360. 11:44reduce everything that is routine and
  361. 11:45boilerplate so that it isn't done by
  362. 11:47hand, but generated instead.
  363. 11:49And the main focus of writing code is on
  364. 11:52the logic. That is, where the business
  365. 11:54logic, entities, some wrapper around
  366. 11:56them, and so on, reside. By the way,
  367. 11:58that’s also interesting. I actually had
  368. 12:00to force it, because it doesn't do this
  369. 12:02by default, to force the AI to move this
  370. 12:04into a separate layer. I mean, it can be
  371. 12:06called different things. Let’s just call
  372. 12:08it a service layer for simplicity. It
  373. 12:10doesn't necessarily mean there are
  374. 12:11specific classes, services, etc., but
  375. 12:13rather a separate layer where the actual
  376. 12:15business logic lives.
  377. 12:17It was quite funny that while I was
  378. 12:18generating this project, I had a certain
  379. 12:21picture in my head of how to do it right
  380. 12:23, how to build layer interactions, who
  381. 12:24is responsible for what, where
  382. 12:26everything goes, and how to write tests
  383. 12:28.
  384. 12:29What did I do?
  385. 12:30I launched an agent and asked it to do
  386. 12:32some research, that is, to open all
  387. 12:33similar projects on GitHub—well, not all
  388. 12:35of them, but the top ten most popular
  389. 12:37ones written in Go—and analyze their
  390. 12:39architecture, comparing it specifically
  391. 12:41with what I have done.
  392. 12:43It turned out to be quite funny that in
  393. 12:46terms of isolating logic into separate,
  394. 12:48independently testable services that
  395. 12:50generalize business operations—all
  396. 12:53business operations—there seem to be
  397. 12:55almost no such projects.
  398. 12:57So, he gave me a report; I have the
  399. 12:59research, and by the way, it’s publicly
  400. 13:00available. You can open the Docs
  401. 13:02research folder and find the document
  402. 13:05where he shows that many of them don't
  403. 13:07even have this layer defined. There’s a
  404. 13:10lot of duplication, and he specifically
  405. 13:12noted that this project, called
  406. 13:13Sphericon, is done better in this regard
  407. 13:15.
  408. 13:16I still had a few shortcomings that I’m
  409. 13:18fixing right now, but overall he noted
  410. 13:20that from an architectural layering
  411. 13:21perspective, it’s more structured than
  412. 13:24all the other projects he looked at.
  413. 13:26That’s how the story goes.
  414. 13:28I’m not drawing any conclusions from
  415. 13:30this; it’s just that perhaps I have this
  416. 13:33thought because in Go, it’s somewhat
  417. 13:35denied or there aren't—not that there
  418. 13:37aren't established practices, but it's
  419. 13:39discussed less, and maybe given less
  420. 13:41attention because there’s an element of
  421. 13:44"we’re not like everyone else," right.
  422. 13:47But in practice, you get what you get,
  423. 13:49because this leads to duplication and
  424. 13:51smears the logic. In short, there are
  425. 13:53all sorts of different problems, but
  426. 13:54these are purely architectural things.
  427. 13:56So, even though, as you can see, the
  428. 13:58code isn’t written by hand, I never
  429. 14:00allow it to just generate whatever
  430. 14:02nonsense it wants. No, there are clear
  431. 14:04layers—in fact, there are many of them—
  432. 14:06and their areas of responsibility must
  433. 14:08be followed. If there’s a bug inside,
  434. 14:10well, that’s not a disaster; it will be
  435. 14:12covered by tests and will eventually be
  436. 14:13fixed one way or another, because it is
  437. 14:15being checked.
  438. 14:16Plus, there will be all sorts of error
  439. 14:18collectors, logs, tracing, everything
  440. 14:20under the sun, and metrics.
  441. 14:22I will never neglect that.
  442. 14:26It doesn’t depend on the level of the AI
  443. 14:28, because, well, the AI isn't capable—
  444. 14:30it's not magic that just takes
  445. 14:31everything in and solves all your
  446. 14:33problems for you.
  447. 14:35No, but of course, looking specifically
  448. 14:37into a concrete piece of code to see
  449. 14:39what’s happening there is not always
  450. 14:40necessary at all. That is true. By the
  451. 14:42way, regarding that, you know, I’m
  452. 14:44deliberately putting that point off. I
  453. 14:45have material in preparation on this
  454. 14:47topic about what code quality actually
  455. 14:48is, why you need to look at it, why you
  456. 14:50don't, where I will explain this
  457. 14:51position in more detail. I just don’t
  458. 14:53want to focus on it right now because
  459. 14:55it’s a bit of a separate issue, and it
  460. 14:57was quite funny. Let me just give you an
  461. 14:59example. Since I talk about this a lot,
  462. 15:01obviously, I get all kinds of different
  463. 15:02comments.
  464. 15:03In one place, a guy wrote a comment that
  465. 15:05he either disagrees or something, but
  466. 15:07the main thing is he gave an example:
  467. 15:08what if it uses concatenation instead of
  468. 15:10interpolation? Like, I don't trust it.
  469. 15:13And I realized how different our
  470. 15:15understanding of code quality and code
  471. 15:16architecture is, right?
  472. 15:18Because for me, what he’s describing is
  473. 15:20not at all what one should be focusing
  474. 15:22on. Firstly, a linter should be tracking
  475. 15:24that. Secondly, it has absolutely
  476. 15:25nothing to do with the actual quality we
  477. 15:27are talking about.
  478. 15:29But again, I won't go into detail on
  479. 15:31this thought right now, because it's
  480. 15:34such an important, separate topic that I
  481. 15:36want to cover it in a dedicated webinar
  482. 15:39—well, a podcast—and write several
  483. 15:41pieces on it.
  484. 15:43Yeah. That’s roughly the kind of circus
  485. 15:45that goes on. By the way, I just
  486. 15:47realized that, in principle, I can even
  487. 15:50show it, since I’ll be demonstrating
  488. 15:52various things today.
  489. 15:54Let me show you TypeSpec separately so
  490. 15:56you can see roughly what it looks like.
  491. 16:00So, this is the API design.
  492. 16:02On the left, we have the descriptions of
  493. 16:04the models, resources, and the API in
  494. 16:07general. And on the right, accordingly,
  495. 16:09is the Open API thing that gets
  496. 16:11generated.
  497. 16:12The spec, firstly, as you can see, turns
  498. 16:14out much longer, it's much harder to
  499. 16:16analyze and look at because it’s more
  500. 16:17machine-oriented, let’s say.
  501. 16:20TypeSpec, thanks to good tooling around
  502. 16:23it—like LSP support and checkers—is
  503. 16:26actually compiled, so it’s also
  504. 16:28well-verified.
  505. 16:30It can, in short, verify a lot more
  506. 16:31different things. That is, you need to
  507. 16:33write more boilerplate code around Open
  508. 16:35API to do the things you need.
  509. 16:37TypeSpec allows you to remove all that,
  510. 16:39to express it in more classic and
  511. 16:41familiar terms like models,
  512. 16:42relationships, interfaces, and so on.
  513. 16:44And thanks to this, not only is a lot of
  514. 16:46code reduced, but the level of
  515. 16:48understanding and control increases
  516. 16:50significantly. So, it's a cool thing. I
  517. 16:52recommend it to everyone who hasn't used
  518. 16:54it yet and is thinking about it. And
  519. 16:56I’ll just show you that here, when I
  520. 16:58talk about emitters, it's an important
  521. 17:00thing. You don't necessarily have to
  522. 17:02turn it into Open API right away. You
  523. 17:04can, in principle, create any emitters
  524. 17:06directly from TypeSpec. Moreover, it is
  525. 17:08extensible. So, roughly speaking, if you
  526. 17:11find OpenAPI to be limited in some way,
  527. 17:13TypeSpec is less restricted, it has many
  528. 17:15more possibilities, and therefore you
  529. 17:18can incorporate features into it that
  530. 17:20aren't in OpenAPI and write emitters
  531. 17:22directly. And ultimately, if they, say,
  532. 17:24really get serious about this,
  533. 17:26converting to OpenAPI, in principle,
  534. 17:27won't be necessary. You will be able to
  535. 17:29emit exactly what you need right away.
  536. 17:31Well, notice here that, sure, there's
  537. 17:33JSON schemas, just OpenAPI, they can
  538. 17:36emit Protobuf, GraphQL, and right now
  539. 17:38they are making clients for four
  540. 17:40languages: Java, Python, JavaScript, C#
  541. 17:42, and JavaScript servers; well, it's
  542. 17:44clear that there's still a lot to be
  543. 17:46added here.
  544. 17:47I hope they are working on it.
  545. 17:50It seems like, if you go to GitHub,
  546. 17:51let's see when their last commit was
  547. 17:53from Microsoft.
  548. 17:546 hours ago. So, in short, they are
  549. 17:56actively working on it. Anyway, that's
  550. 17:58good. I believe in this thing and will
  551. 18:01be a bit of an ambassador for it.
  552. 18:03So I've sort of become a little bit of a
  553. 18:05Microsoft ambassador in this area.
  554. 18:07So, um, I recently wrote a post, and
  555. 18:10it's not just a post.
  556. 18:12It turned out that when I started
  557. 18:15building this thing in Go, I saw a large
  558. 18:17number of, firstly, certain changes in
  559. 18:20my process, and secondly, a lack of some
  560. 18:22tools that I needed to add. And now I'm
  561. 18:25going to tell you about all of them. Why
  562. 18:27, by the way, someone might say, "
  563. 18:29Kirill, why are you using these new
  564. 18:30trendy buzzwords like 'Quality Gates'?"
  565. 18:32What kind of crap is that? Why don't you
  566. 18:34just say 'linters'? Yeah, well, I would
  567. 18:35think the same thing. Well, on one hand
  568. 18:37, you could say that, but on the other,
  569. 18:39I want to emphasize that all this is
  570. 18:41moving towards automation, and secondly
  571. 18:43, the range of capabilities is
  572. 18:45broadening slightly, things that, well,
  573. 18:47were never done with linters before and
  574. 18:49weren't thought of that way. For example
  575. 18:51, modern tools, they already look at the
  576. 18:53architecture in a sense, right? Formally
  577. 18:55, you could call them linters too, but
  578. 18:57the effect is different. I mean, you
  579. 18:59want to understand that our task is not
  580. 19:01to do this for ourselves, but we are
  581. 19:03doing it for the AI, so it can
  582. 19:05automatically verify what it's doing,
  583. 19:07specifically in a loop, right? So it
  584. 19:09made something, ran it, saw the errors,
  585. 19:11fixed them, and in this way, accordingly
  586. 19:13, it moves forward. So, in this
  587. 19:15terminology, it's called quality gates.
  588. 19:17And in this direction, the development
  589. 19:19of all further thought will proceed. So
  590. 19:22, what did I do? Let me demonstrate it
  591. 19:24to you.
  592. 19:25I created a repo called Death Quality
  593. 19:28Gates.
  594. 19:29Note that I've already received pull
  595. 19:30requests and it has reached 145 stars.
  596. 19:33That's pretty good. How, again, does
  597. 19:35this differ from, say, a regular list of
  598. 19:37linters for different languages?
  599. 19:40It differs because, in reality, if you
  600. 19:42dig deep, it turns out there are many
  601. 19:45tools that go well beyond the things
  602. 19:47we're used to.
  603. 19:49When we think about linters—let me give
  604. 19:51you some examples—first of all, sure,
  605. 19:53there’s security-related stuff, but
  606. 19:54there are also cool things, for example
  607. 19:56, related to Markdown. I mean, what are
  608. 19:58we usually used to? Well, in Markdown,
  609. 20:00they look at headers and things like
  610. 20:01that, but there's a tool, for instance,
  611. 20:03that looks for links and checks if
  612. 20:05they’re broken or not. Especially
  613. 20:06cross-links between Markdown documents.
  614. 20:08A really cool thing. Next is a
  615. 20:10spellchecker that checks for various
  616. 20:12errors. Well, that's a pretty obvious
  617. 20:13thing, right? Then there is an awesome
  618. 20:15linter. For us, as people who create
  619. 20:18courses and have many thousands of
  620. 20:19Markdown files with code examples that
  621. 20:22need constant maintenance, this is a
  622. 20:24lifesaver, because it’s not just a
  623. 20:26Markdown linter and formatter. It’s a
  624. 20:28cool extensible system that connects
  625. 20:31specific linters and formatters directly
  626. 20:33for code snippets. And, accordingly, all
  627. 20:36the code we have—we have a huge
  628. 20:39meta-repo that contains a ton of other
  629. 20:41repositories with courses and practices
  630. 20:44—it just en masse runs them through this
  631. 20:47, uh, Markdown—again, I guess you could
  632. 20:50call it that, but it includes everything
  633. 20:53—in short, through this tool, which not
  634. 20:56only checks Markdown, but also checks
  635. 20:58the code inside it using its linters and
  636. 21:01formatters. And this is, of course,
  637. 21:03fantastic, because before, with such
  638. 21:04volumes, you’d simply get exhausted from
  639. 21:06constantly fixing and cleaning things up
  640. 21:07. Especially when standards change in
  641. 21:09some languages, like: "Oh, now everyone
  642. 21:11move here." Like, we used to put a
  643. 21:12semicolon, but now we don’t. And you
  644. 21:14have to change that in thousands of
  645. 21:16files. Well, there’s always something to
  646. 21:17do, right? On the other hand, people
  647. 21:19also want to see that everything is
  648. 21:20implemented correctly, so this helps us
  649. 21:22with that. But it’s useful in more cases
  650. 21:23than just this one. So if you're writing
  651. 21:25any kind of documentation that includes
  652. 21:26code examples, honestly, it's just
  653. 21:28beautiful. Basically, there's an epic
  654. 21:30amount of stuff gathered here.
  655. 21:32It covers Git hooks, Git conventions—
  656. 21:35basically checking how we commit our
  657. 21:37code. A new tool has appeared that
  658. 21:40checks agent configurations, configs,
  659. 21:43MCPs, skills, and so on. You have to set
  660. 21:46up custom rules there. What else do we
  661. 21:48have? There's the obvious Dockerfiles
  662. 21:50and all the infrastructure stuff.
  663. 21:53There's a bot like Dependabot—for those
  664. 21:56who don't know, it's a free automated
  665. 21:58GitHub bot you connect to GitHub Actions
  666. 22:01, and it constantly sends you pull
  667. 22:03requests with updates and security
  668. 22:05patches.
  669. 22:08If you're on GitLab, you don't have that
  670. 22:09, but there's a bot called Renovate, and
  671. 22:11it does exactly the same thing.
  672. 22:14So, if you haven't connected it yet, now
  673. 22:16is the time to do it. There are error
  674. 22:18scanners, and there's this cool thing
  675. 22:21called Gitleaks that finds secrets if
  676. 22:23something has leaked. Again, just in
  677. 22:25case an agent did it by accident, even
  678. 22:27though they usually watch that closely,
  679. 22:29you never know, right? You don't want
  680. 22:30things leaking. And so on. There are
  681. 22:32things for specific languages, and there
  682. 22:34are some separate items I’ll explain now
  683. 22:36. By the way, there's this cool tool
  684. 22:37called Limit that checks your bundle
  685. 22:39size, for example, and tells you if
  686. 22:40you’ve done something wrong in your
  687. 22:42frontend. Do you know what the coolest
  688. 22:43part of this whole situation is? With
  689. 22:45all these lists in the past, what was
  690. 22:46always the problem? Everyone would put
  691. 22:48them together and say, "Oh, cool." You’d
  692. 22:50bookmark them, share them, but what
  693. 22:51comes next? Actually implementing and
  694. 22:53applying all of that is a huge problem.
  695. 22:55So, here’s how the modern approach works
  696. 22:58: having looked at the best cutting-edge
  697. 23:00techniques, I created a section called "
  698. 23:02It in your project," where you are
  699. 23:04simply given—my god!
  700. 23:06—a prompt snippet that you copy, and it
  701. 23:08just goes through this list, compares it
  702. 23:10to what you have, and tells you what you
  703. 23:12can change. And it actually works really
  704. 23:15well. I mean, I haven't seen anything
  705. 23:16like this before. Now people are writing
  706. 23:18in the comments: "Hey, I ran it, and it
  707. 23:20found four tools for me," they even send
  708. 23:21me screenshots, and people are just
  709. 23:23happy that they got something working.
  710. 23:25And I'm just like, "Damn, that's cool."
  711. 23:26There was no such range before. And now
  712. 23:27you can generally think about the things
  713. 23:30you do in this way. So, I highly
  714. 23:32recommend looking at what's happening
  715. 23:34from this perspective. By the way, you
  716. 23:35can perform updates in this manner.
  717. 23:37Meaning, when you have a guide, a
  718. 23:39migration guide from one thing to
  719. 23:40another, it can be more in the form of a
  720. 23:42prompt so that it can be fed into a
  721. 23:43machine and it does everything itself.
  722. 23:45But when I was doing all this, my goal
  723. 23:47wasn't just, you know, like an "awesome
  724. 23:49list" where they collect absolutely
  725. 23:50everything that exists.
  726. 23:53My goal was to curate a list of what I
  727. 23:55consider to be genuinely cool, because
  728. 23:57there are many similar tools, yes, but I
  729. 24:00have my own specific criteria for what
  730. 24:02is good and what is bad, what is
  731. 24:04promising and what is not.
  732. 24:07That's why, first of all, I named it a
  733. 24:09bit differently and explained right at
  734. 24:11the beginning that these are my personal
  735. 24:13preferences: one tool per task, if
  736. 24:15possible. They just overlap sometimes,
  737. 24:17so it's not always perfect. And it
  738. 24:19turned out that a lot of things people
  739. 24:21recommended to me later, or just wrote,
  740. 24:23"Kirill, check this out, do you have
  741. 24:25this?" No. How else did I do it?
  742. 24:28I don't just add them there; there is a
  743. 24:30folder inside the repository called "
  744. 24:32research," where I force the AI first—
  745. 24:34and naturally, everyone who sends pull
  746. 24:36requests—to conduct deep research on
  747. 24:38what is better and how it's used.
  748. 24:40Well, in general, a bunch of different
  749. 24:42aspects are checked there. And all the
  750. 24:44tools that were sent to me, sometimes
  751. 24:46I'd think, "Oh, maybe I really need this
  752. 24:48one?" I run it through there, and it
  753. 24:50tells me, "Listen, I’ve already done
  754. 24:51that research because I asked the agent
  755. 24:52to study everything that exists."
  756. 24:54"This tool is worse than ours for such
  757. 24:56and such reasons." In the end, I think
  758. 24:58only a couple were added, and even then
  759. 24:59, only in languages I hadn't covered
  760. 25:01initially. Something was added to Elixir
  761. 25:03and, maybe in Rust, I think something
  762. 25:04was add—wait, no, there were three or
  763. 25:06four, but those were brand new topics.
  764. 25:08But whenever I was shown an existing one
  765. 25:11that was already on the list, the one I
  766. 25:14already had always won. So all the
  767. 25:16others turned out not to be the right
  768. 25:18ones. Well, usually, you know, firstly,
  769. 25:19these are modern Rust-based tools.
  770. 25:21Secondly, there’s still a certain level
  771. 25:22of popularity, integration, and so on.
  772. 25:24Now, there are some things I really want
  773. 25:26to talk about separately. So, in essence
  774. 25:28, today will be a sort of review.
  775. 25:31I’ve partially mentioned this in my
  776. 25:33channel, but I want to voice it out,
  777. 25:35talking about the tools I’ve made or use
  778. 25:37and highly recommend to you.
  779. 25:40So, today is kind of an open-source
  780. 25:42advertisement in a sense. And I won’t be
  781. 25:44focusing on "look at this tool I made,"
  782. 25:46but rather on the problem itself,
  783. 25:48because it's very likely you haven't
  784. 25:50looked at it this way or thought about
  785. 25:52such an approach.
  786. 25:54And this might somehow help or give you
  787. 25:55a hint. I’ve been creating Hexlet
  788. 25:58courses since 2013. Right now, we are
  789. 26:00actively moving toward artificial
  790. 26:01intelligence. Agentic programming,
  791. 26:03automation, low-coding, and LLM
  792. 26:05programming. All of this is becoming a
  793. 26:07key direction in the near future. If you
  794. 26:09want to increase your productivity,
  795. 26:11implement AI-based solutions in your
  796. 26:13work, or start your own projects, you’ve
  797. 26:16come to the right place. You can look at
  798. 26:18specific training programs via the link
  799. 26:20in the description.
  800. 26:21Let me start with something I talk about
  801. 26:24regularly, but there's a nuance, and it
  802. 26:26needs to be said again.
  803. 26:28So, there’s this concept that you
  804. 26:31generally need to set up specific
  805. 26:33versions of languages and SDKs for each
  806. 26:36project, and you can’t really do that
  807. 26:39manually by default.
  808. 26:43That is, as a rule, if you have a Mac or
  809. 26:45, say, Ubuntu, your installers do
  810. 26:47everything globally, so you can't easily
  811. 26:49separate language versions.
  812. 26:52There are many different version
  813. 26:54managers. They are called version
  814. 26:56managers. It's very important not to
  815. 26:57confuse them with package managers,
  816. 26:58because a package manager handles
  817. 26:59packages for a specific language. Here,
  818. 27:00we mean the language itself: its
  819. 27:02interpreter, compiler, or whatever it is
  820. 27:04that makes it run.
  821. 27:05Accordingly, there is essentially such a
  822. 27:08tool for every language.
  823. 27:09But when you write in different
  824. 27:11languages, it becomes a problem, because
  825. 27:13, well, you'll get exhausted having to
  826. 27:15install these tools, update them, and
  827. 27:17manage things through them. And it's
  828. 27:19different everywhere. That’s why, at
  829. 27:21some point, the asdf tool became popular
  830. 27:23. It appeared many, many years ago, it
  831. 27:25was recommended to me, and I switched to
  832. 27:27it. But asdf was from before the Rust
  833. 27:29era, and it sort of got stuck there. And
  834. 27:31besides that, it honestly didn't have
  835. 27:33the simplest user interface. I forgot
  836. 27:35how to use it every single time, to be
  837. 27:36honest. But it did solve the problem
  838. 27:38well enough. And at some point, a guy
  839. 27:41showed up, some crazy open-sourcer who
  840. 27:44created mise.
  841. 27:46First off, it's written in Rust.
  842. 27:47Secondly, it's a super-fast tool.
  843. 27:50Thirdly, it's much simpler from an
  844. 27:51interface perspective. And that's
  845. 27:53exactly how it started. Moreover, I
  846. 27:55really want to mention this, because I
  847. 27:56explained it to some people in messages
  848. 27:58and they were shocked.
  849. 28:00Since it's been around for a while and
  850. 28:02many aren't following the updates, many
  851. 28:04still think it's just a thing that
  852. 28:06installs languages.
  853. 28:08I want to dedicate about 10 or 15
  854. 28:10minutes to it, to tell you what it has
  855. 28:12actually turned into, so you understand
  856. 28:15that right now it can replace a ton of
  857. 28:17various tools, custom scripts, and hacks
  858. 28:19, and work as a unified system to manage
  859. 28:22your entire development process. It’s
  860. 28:24just fantastic, guys. Honestly, I can't
  861. 28:26help but promote it, simply because it’s
  862. 28:28an insanely cool tool.
  863. 28:29By the way, I call it "mise," but it’s
  864. 28:31written there that it’s pronounced "
  865. 28:33meez." So, in reality, it should be
  866. 28:34called "meez." It's strange because I've
  867. 28:36never actually heard how it's pronounced
  868. 28:38. And you see, it turns out I’ve been
  869. 28:39pronouncing it wrong the whole time. Let
  870. 28:40me call it "mise" as it's written, and
  871. 28:42explain how it works. So, let's start
  872. 28:44like this. By default, you can clearly
  873. 28:46see it as a tool. It determines which
  874. 28:49Node, Python version, and so on, to
  875. 28:53install. Indeed, it all started with
  876. 28:55that, but that was just the beginning.
  877. 28:58After that, one of the next steps was
  878. 29:00expanding to the point of "let's just
  879. 29:02install anything."
  880. 29:04What's the difference if it's a language
  881. 29:06or something else? If you can install
  882. 29:08something via apt or brew, well, we can
  883. 29:10install any damn thing. That's why mise
  884. 29:12currently installs basically anything
  885. 29:14you want. And it does this from almost
  886. 29:16anywhere. What's very nice is that you
  887. 29:19don't need to worry; if you run this
  888. 29:22project with this config on different
  889. 29:24operating systems, it will simply ignore
  890. 29:27what isn't there. So you don't even have
  891. 29:29to keep track of that.
  892. 29:30This is also great, as it allows you to
  893. 29:33create cross-platform deployment
  894. 29:34environments based on it.
  895. 29:37So, for example, I have any tools there
  896. 29:39that are additionally needed for the
  897. 29:42project to work. And it doesn't matter
  898. 29:44if they might also be specified in a
  899. 29:45neighboring folder.
  900. 29:47It doesn't matter at all, because it
  901. 29:49will install and handle everything
  902. 29:50correctly and efficiently. Ah, so what’s
  903. 29:52included there?
  904. 29:53Let me just show you as an example what
  905. 29:55kind of tools I install in this project
  906. 29:57of mine, besides the languages.
  907. 30:01We’ll go into the source code now; it
  908. 30:02might lag a little because I have about
  909. 30:04five agents running in the background.
  910. 30:06So, here’s the config. Just look at the
  911. 30:08list of tools, right? There are
  912. 30:11basically two screens of them. What can
  913. 30:14I say? Uh, there are utilities here,
  914. 30:16languages, all sorts of linters, and
  915. 30:20checkers. And notice, they’re installed
  916. 30:23from GitHub, from Homebrew, and from NPM
  917. 30:26. In short, from everywhere. I think
  918. 30:28even C ++ is built directly here. It
  919. 30:30seemingly just compiles it itself. In
  920. 30:32short, it’s really cool. You can define
  921. 30:35anything you want this way. Note that
  922. 30:37some versions are pinned, while others
  923. 30:38are set to "latest," and it just
  924. 30:40installs them. Well, because for those,
  925. 30:41it’s not critical. That’s kind of a
  926. 30:42separate thing. I just want the latest
  927. 30:44one. A web server is installed, some
  928. 30:46kind of Caddy or CoreDNS, since we use
  929. 30:48DNS there for specific tasks. There’s a
  930. 30:50lot of stuff. That was the first thing
  931. 30:53that appeared. Here’s its extension.
  932. 30:54Second, that means managing environment
  933. 30:57variables. It sets them, it, uh, loads
  934. 31:00them.
  935. 31:02And most importantly—and you’ll see why
  936. 31:04this becomes significant—because Mise
  937. 31:06eventually expanded to cover almost all
  938. 31:08standard development tasks, this
  939. 31:10management of environment variables
  940. 31:12helps it automatically propagate
  941. 31:14everything everywhere: whether it’s
  942. 31:16tasks, running programs, hooks, and so
  943. 31:18on and so forth.
  944. 31:21Usually, this is a bit of a headache
  945. 31:23when you have to use all kinds of tricky
  946. 31:25mechanics, with various tools stored
  947. 31:27here, and separate tasks kept over there
  948. 31:29.
  949. 31:30All that kind of stuff. Let’s move on.
  950. 31:33So, the next thing it started doing: it
  951. 31:36suddenly took over the task-running
  952. 31:38history, meaning what Make or other
  953. 31:40runners usually do.
  954. 31:43If you remember, I always advocated for
  955. 31:45Make. And despite the existence of many
  956. 31:48different runners, mostly written in Go
  957. 31:50, by the way, and quite popular ones too
  958. 31:53, I somehow avoided them. I thought it
  959. 31:55was just another tool. There generally
  960. 31:57wasn't any point to it, as a rule. Make
  961. 31:59covered almost everything. Sometimes
  962. 32:01bash scripts, but then again, the IDE
  963. 32:02writes those. So, it feels like there
  964. 32:03are no problems at all. Yeah, Make
  965. 32:05doesn't show you the commands, but it
  966. 32:06feels like you're running them manually
  967. 32:08much less often now anyway.
  968. 32:10But on the other hand, why did I
  969. 32:11ultimately switch—if you look at the
  970. 32:13source code now, I’ve moved from
  971. 32:15Makefiles to mise everywhere, which is
  972. 32:17fantastic for me, because I’ve been
  973. 32:19advocating for Make since, like, 2011,
  974. 32:21and I used it in all my projects for 15
  975. 32:23years and was absolutely happy.
  976. 32:25And for only one reason: because mise,
  977. 32:28its system, is integrated with
  978. 32:30everything going on inside it.
  979. 32:33And since I’m not the one writing or
  980. 32:35monitoring it anyway, it’s much more
  981. 32:36convenient for me to have one tool that
  982. 32:38manages absolutely everything. Well,
  983. 32:40obviously. And plus, actually, there are
  984. 32:41, of course, some convenient features
  985. 32:42there. Like, you type "run," and you get
  986. 32:45a fuzzy search for the tasks that are
  987. 32:47available. I mean, there are really a
  988. 32:50lot of cool little features that truly
  989. 32:52improve the developer experience
  990. 32:53significantly. That’s why, in the end,
  991. 32:56it grew on me, and we’ve switched to it
  992. 32:58everywhere. And it has plenty of other
  993. 33:00features too. I’ll be honest with you,
  994. 33:02the guy is crazy; he releases it every
  995. 33:04single day, and every day there are just
  996. 33:06tons of changes. I am absolutely amazed
  997. 33:08by how much he gets done and how
  998. 33:09powerful this tool is. Look at what he
  999. 33:11does next. He implemented hooks into it
  1000. 33:13. So, this thing also replaces all your
  1001. 33:16git-hook, git-simple-hook, and so on and
  1002. 33:18so forth. And at the same time, it can
  1003. 33:20run its own commands internally using
  1004. 33:22its own environment variables. Super,
  1005. 33:24everything is integrated once again. And
  1006. 33:26look, this isn’t the end.
  1007. 33:28It has a bootstrap function, so it can
  1008. 33:31be used as a system deployment tool,
  1009. 33:33roughly speaking. So you're setting up
  1010. 33:36your computer from scratch, and
  1011. 33:38obviously, you still need to configure
  1012. 33:39things, no matter what, regardless of
  1013. 33:41the IDE you’re using. And I’ll show you
  1014. 33:43what I did now. I had my dotfiles, which
  1015. 33:46, by the way, are quite popular. A lot
  1016. 33:48of people keep an eye on them. And
  1017. 33:50before, there was a lot of manual work
  1018. 33:51involved there. It used things like
  1019. 33:53Docker, and I had to set up symlinks and
  1020. 33:56so on.
  1021. 33:57If you look, notice the activity—for a
  1022. 33:59long time I was doing minor things here
  1023. 34:01and there, and then there’s this spike.
  1024. 34:03That spike happened recently for the
  1025. 34:06sole reason that mise forced me to
  1026. 34:08completely rethink my entire approach.
  1027. 34:11Accordingly, first of all, it's clear
  1028. 34:13that various agent skills and so on have
  1029. 34:14appeared here, but most importantly,
  1030. 34:16note that everything has simply come
  1031. 34:18down to Miz. In essence, there is
  1032. 34:19nothing else here. First, he didn't
  1033. 34:21restructure it as is customary; he
  1034. 34:22created the home directory specifically
  1035. 34:24using the folders that are laid out so
  1036. 34:26they match exactly for symlinking. So,
  1037. 34:28what else does Miz do besides that?
  1038. 34:30First, there is the Bootstrap, as I
  1039. 34:32already said, which actually sets up the
  1040. 34:33application from scratch.
  1041. 34:35And what is also very important, it has
  1042. 34:37dotfile management, meaning setting up
  1043. 34:39symlinks, what to delete, update, and
  1044. 34:41all that kind of thing. Now I'll open
  1045. 34:43its config, yes, it's quite...so here's
  1046. 34:46my config, you see, it's almost 400
  1047. 34:48lines of code.
  1048. 34:49What’s in it. So, first, so you
  1049. 34:52understand, it directly handles command
  1050. 34:55line settings and things like that, like
  1051. 34:58Bash or Zsh. It even configures my macOS
  1052. 34:59settings directly.
  1053. 35:01I mean, there are some things when I'm
  1054. 35:02setting up that I need to tweak, for
  1055. 35:04example, which gestures I want to enable
  1056. 35:05.
  1057. 35:06It configures all that history. Next, it
  1058. 35:08knows where, you see, the home is for
  1059. 35:10dotfiles and their default mode is
  1060. 35:12symlinks. It symlinks them. Here are the
  1061. 35:14tools it installs. At the same time,
  1062. 35:16these tools work globally. However, each
  1063. 35:17project can also have its own, right?
  1064. 35:19And accordingly, it installs, for
  1065. 35:20example, bat, if anyone knows it. It’s a
  1066. 35:22tool where you use bat instead of cat,
  1067. 35:25and it outputs the file contents to the
  1068. 35:27screen, but with syntax highlighting. So
  1069. 35:29, it’s a very cool thing. It installs my
  1070. 35:32VS Code dev containers, Docker, Docker
  1071. 35:34Compose, and fzf. Well, in short, if you
  1072. 35:37look, there’s just a ton of various
  1073. 35:38utilities that are used globally. And
  1074. 35:40ripgrep, some pandoc, yes, what else do
  1075. 35:43we have? Terraform, treesitter is needed
  1076. 35:45for something. And so on, in short. And
  1077. 35:49various AWS command-line utilities. In
  1078. 35:51general, everything that is needed
  1079. 35:53overall. And notice, not even just for
  1080. 35:55the command line; for example, my Chrome
  1081. 35:57is updated through this thing. So I made
  1082. 35:59it so that all the software I need is,
  1083. 36:01in principle, installed through this
  1084. 36:03stuff. I believe tools like guests are
  1085. 36:05also installed here. So it turns out
  1086. 36:07that it sets up not just purely
  1087. 36:09developer things, it basically sets up
  1088. 36:11my entire system. There. And,
  1089. 36:14accordingly, the Bootstrap even sets up
  1090. 36:15Brew, since it's not there by default.
  1091. 36:17Just look at how many packages are
  1092. 36:19installed via Brew. Telegram, Slack,
  1093. 36:21WhatsApp, ChatGPT, CLI, OBS, Audacity—
  1094. 36:23that's all for recording. Zoom, NordVPN
  1095. 36:26, I use GCloud, and MK installs and even
  1096. 36:30updates itself. In short, it's just
  1097. 36:32beautiful. There's even an Oh My Zsh
  1098. 36:34configuration here.
  1099. 36:36And various features with dotfiles. Just
  1100. 36:39wow.
  1101. 36:41And the last major thing it does, as I
  1102. 36:43already mentioned, you should explore it
  1103. 36:45yourself because it has a ton of
  1104. 36:47features.
  1105. 36:49You might be surprised, but not everyone
  1106. 36:51likes or wants to work with Docker
  1107. 36:53Compose. To give you some context, I was
  1108. 36:55one of those people who, back when it
  1109. 36:57first appeared, acted as a kind of
  1110. 36:59advocate for it. I moved all my projects
  1111. 37:01over to Docker Compose. I recommended it
  1112. 37:04to everyone and trained people on it. So
  1113. 37:05, in a way, I contributed to Docker
  1114. 37:07Compose being actively used everywhere.
  1115. 37:10But, honestly, as time went on, there
  1116. 37:13were more and more issues related to
  1117. 37:16performance.
  1118. 37:18On Macs, it's still honestly a problem
  1119. 37:21with resources—the overall management,
  1120. 37:23having some things inside and others
  1121. 37:25outside, caches, the need for quick
  1122. 37:27dependency updates, and so on.
  1123. 37:30In short, a whole bunch of other
  1124. 37:32problems started popping up. I mean, it
  1125. 37:34seems like there’s isolation and all
  1126. 37:35that. In production, it’s clearly very
  1127. 37:37necessary and cool, but in development,
  1128. 37:39in reality—especially considering the
  1129. 37:41emergence of tools that set everything
  1130. 37:44up automatically (since the problem used
  1131. 37:46to be just setting it up)—the
  1132. 37:48performance issues have become
  1133. 37:49full-blown, absolutely massive. And for
  1134. 37:52me, this shows up a lot because I often
  1135. 37:54have many Docker containers running in
  1136. 37:57parallel specifically for practice tasks
  1137. 37:59. It turns out that when a project is
  1138. 38:01running in Docker at the same time, my
  1139. 38:03Docker literally freezes. Something
  1140. 38:04happens regularly because there's so
  1141. 38:06much—to give you an idea, I have about
  1142. 38:09150 GB actively used by Docker images.
  1143. 38:11That’s how much I have to build and run
  1144. 38:13there. Well, that's just a
  1145. 38:15Hexlet-specific thing.
  1146. 38:17I just realized that I don't want my
  1147. 38:18main project to depend on Docker,
  1148. 38:19because I’d rather turn it off so it
  1149. 38:20doesn't get in my way.
  1150. 38:22And in the end, we did it semi-manually
  1151. 38:24.
  1152. 38:26You know, if anyone still remembers
  1153. 38:27Procfiles or Foreman—that thing that
  1154. 38:30could manage and launch processes—it was
  1155. 38:32always a bit of a manual chore because
  1156. 38:34you had to set everything up and
  1157. 38:36configure it yourself.
  1158. 38:38Well, now Mise has implemented that
  1159. 38:40functionality internally. It has a
  1160. 38:43mechanism like that. I'll try to check
  1161. 38:45now if it's here in the docs or not. Ah
  1162. 38:47, well, just look at how many things it
  1163. 38:49does. It's called "daemons."
  1164. 38:52Essentially, it's a separate utility,
  1165. 38:55and Mise has become sort of an umbrella
  1166. 38:57tool that connects many of its other
  1167. 39:00tools.
  1168. 39:02So, it's a separate thing integrated
  1169. 39:04into it, which is managed via Mise,
  1170. 39:06effectively replacing—let's call it—
  1171. 39:08Docker Compose, but for regular
  1172. 39:09processes.
  1173. 39:11And that doesn't mean, by the way, that
  1174. 39:13you can't even spin up containers there
  1175. 39:14too. In fact, you describe the daemons
  1176. 39:16you have in the very same config file.
  1177. 39:19It can, for example, share ports or
  1178. 39:21distribute them, so there are many
  1179. 39:22features like that. It can start them,
  1180. 39:25restart them, or start a whole set if
  1181. 39:27needed. It shows their logs. Just the
  1182. 39:29same. In short, it's an absolutely
  1183. 39:31identical thing, but without using
  1184. 39:32Docker Compose. Here is an example of
  1185. 39:34how it's structured. See, there are
  1186. 39:35tools, daemon descriptions, and tasks.
  1187. 39:38So, you see, it's really cool that this
  1188. 39:39is all done in one place. I didn't fully
  1189. 39:41realize before how great it is when it's
  1190. 39:43a single tool. Now you can see it, and
  1191. 39:45it works amazingly well.
  1192. 39:48Anyway, you can look at this yourself in
  1193. 39:50the projects I'm talking about here.
  1194. 39:53Yes, it's all public, everything is open
  1195. 39:54.
  1196. 39:55For instance, here are my daemon
  1197. 39:57descriptions: a database, Mailpit—a
  1198. 40:00separate utility where the mail we send
  1199. 40:02goes.
  1200. 40:04DNS runs separately, then the backend,
  1201. 40:05frontend, and Dite—something else
  1202. 40:07interesting. Actually, I don't even know
  1203. 40:09what that thing is. Some contract, some
  1204. 40:11server. Well, anyway, Caddy, and by the
  1205. 40:14way, Mise can also sync skills.
  1206. 40:17I wouldn't be surprised—in fact, I'm
  1207. 40:18confident—that it's heading toward fully
  1208. 40:21managing the setup of things like MSC,
  1209. 40:22MCP servers, skills, and so on.
  1210. 40:25So it will also become a system for all
  1211. 40:27that stuff. Anyway, let me stop talking
  1212. 40:29about it now.
  1213. 40:31I hope, I really want to believe that
  1214. 40:33I've convinced someone to take a look
  1215. 40:35and try it out, because to me, it’s a
  1216. 40:38truly brilliant solution that covers all
  1217. 40:40the basic needs—it’s like a Swiss Army
  1218. 40:42knife, but a proper one.
  1219. 40:44It’s not an attempt to do everything,
  1220. 40:46but an attempt to unite those things
  1221. 40:48that should, in fact, be united. I have
  1222. 40:50a bit of a prediction, if you will. I'll
  1223. 40:52play the part of a psychic for a moment
  1224. 40:54. While the approach used to be—well, it
  1225. 40:56changed sometimes, but in general—let’s
  1226. 40:58build independent utilities, even if
  1227. 40:59they’re cool.
  1228. 41:01Because we can now generate so much, and
  1229. 41:03at a fairly high quality, and
  1230. 41:05furthermore, many things need to be
  1231. 41:07rethought with a modern approach, I’ve
  1232. 41:09started to believe that some super-apps
  1233. 41:11will emerge, similar to how it happened
  1234. 41:13on mobile.
  1235. 41:15I mean, MCP is a great example of why it
  1236. 41:17doesn't make sense anymore to make any
  1237. 41:19of these tasks a separate product that
  1238. 41:21we invest in fully. Indeed, it can all
  1239. 41:23be implemented by a single tool that
  1240. 41:25divides everything between itself,
  1241. 41:27shares resources, and allows us to
  1242. 41:29properly describe and build
  1243. 41:30relationships between them, because it’s
  1244. 41:32ultimately one unified developer toolset
  1245. 41:34that we need when we are actually
  1246. 41:36working. So, I don't know if there are
  1247. 41:38other similar tools on the horizon right
  1248. 41:40now, but I'm certain that, in principle
  1249. 41:42, they should be like this. Therefore,
  1250. 41:43for all those making just a separate
  1251. 41:46tool, say, for managing GitHub, well, to
  1252. 41:48me, the value of such things is dropping
  1253. 41:51sharply. If you recall, there were
  1254. 41:52already many of them, and more have
  1255. 41:54appeared, but what’s the point if they
  1256. 41:56only cover that one part? You still need
  1257. 41:58five or six other tools to cover the
  1258. 41:59whole pipeline. Anyway, MCP has done it
  1259. 42:01. For me, this is the point where you
  1260. 42:04know you can relax; the issue is
  1261. 42:07resolved, and they'll handle any further
  1262. 42:09refinements as needed.
  1263. 42:12I think the only thing left regarding
  1264. 42:13global stuff is that there isn't a
  1265. 42:15universal way to install MCP servers yet
  1266. 42:16. I mean, there’s an approach for Claude
  1267. 42:18, there’s an approach for others, but
  1268. 42:20there’s no universal one yet. I’m sure
  1269. 42:22they will take that on.
  1270. 42:23By the way, I know there are attempts to
  1271. 42:26create utilities that manage everything
  1272. 42:29needed for agents.
  1273. 42:30There are skills for installing skills,
  1274. 42:32but only for skills. Microsoft is trying
  1275. 42:34, for some reason in Python, I don't
  1276. 42:36know why, to build some modern tool that
  1277. 42:38allows you to define a general config,
  1278. 42:40install MCP skills, or maybe something
  1279. 42:41else, like plugins from marketplaces if
  1280. 42:43needed.
  1281. 42:44And now I see and realize that all of
  1282. 42:46this is actually useless. Yes, someone
  1283. 42:48else might try to do something like this
  1284. 42:50or they might succeed, but eventually,
  1285. 42:52once Mistral adds MCP support on top of
  1286. 42:54its skills, that's it—box checked,
  1287. 42:56nothing else is needed; it does
  1288. 42:58everything in one single stroke, so to
  1289. 43:00speak. We're done with that. Maybe I
  1290. 43:02talked about it for a bit too long, but
  1291. 43:04I really wanted to describe it in detail
  1292. 43:06so you could understand the power of
  1293. 43:07this whole system. And by the way, the
  1294. 43:09Evil Martians didn't finish Left. I
  1295. 43:12actually managed to switch to it in a
  1296. 43:14couple of projects. We ran it for a
  1297. 43:15couple of months and that was it, it
  1298. 43:18became obsolete because Mistral appeared
  1299. 43:20with all these features. Let's move on
  1300. 43:22and talk about the rest. So, what did I
  1301. 43:24have to write? I wrote about three or
  1302. 43:27four tools, some partially in Go, some
  1303. 43:29for everything else. I will just go
  1304. 43:32through them now and tell you a little
  1305. 43:34bit about them, because these tools are
  1306. 43:37quite cool in themselves.
  1307. 43:39And, perhaps, they will give you some
  1308. 43:41ideas for your own projects. Let's get
  1309. 43:44started. I'll open them up now and tell
  1310. 43:46you about them. So, let's start with the
  1311. 43:49"heavy" utility.
  1312. 43:51When we work with a large number of
  1313. 43:54agents now, how did we actually work
  1314. 43:56before?
  1315. 43:57Let's say I'm in "main" right now in my
  1316. 43:59project, and I need to get something
  1317. 44:01done. I create a branch, switch to it,
  1318. 44:03and work in it. It's clear that nobody
  1319. 44:04works in several branches in parallel.
  1320. 44:06Meaning you work in one branch, if
  1321. 44:08needed, switch to another or back to
  1322. 44:10main, and somehow juggle all of that.
  1323. 44:12With a multi-agent approach, that's no
  1324. 44:14longer the case. Everything started
  1325. 44:15working in parallel. On the other hand,
  1326. 44:17by the way, people sometimes ask: "How
  1327. 44:19do you manage five sessions in parallel
  1328. 44:20?" There's a trick to it, guys. It's not
  1329. 44:22about us working the old way in five
  1330. 44:24different sessions. It's clear that
  1331. 44:26while task planning is sequential, the
  1332. 44:29execution is parallel. Because this
  1333. 44:30constant micromanagement, where you
  1334. 44:32intervene and say: "Oh, you're doing it
  1335. 44:34wrong, do it this way." That's the old
  1336. 44:35approach. Nobody does it that way
  1337. 44:36anymore. Therefore, as a rule, there is
  1338. 44:38a fairly long sequential design of tasks
  1339. 44:41, but execution happens in parallel. And
  1340. 44:43in general, you don't even have to do
  1341. 44:45this on a computer anymore. You can do
  1342. 44:46it remotely, because in the end, you
  1343. 44:48only look at the final result. But for
  1344. 44:50this to work, obviously, you need
  1345. 44:51something like Spec-Driven Development
  1346. 44:53and all other similar approaches. But
  1347. 44:54that is just to illustrate how people
  1348. 44:56run agents in parallel. Like that. They
  1349. 44:58don't do it as if we just opened five
  1350. 45:00branches at once, yeah, and are just
  1351. 45:02hacking away. So, actually, when we move
  1352. 45:04to such an approach, using pure branches
  1353. 45:07. You just can't use "git switch". Why?
  1354. 45:09Because if one of your agents switches,
  1355. 45:11all the others are like: "Hey, what did
  1356. 45:13you do? I want to do mine too." Yeah.
  1357. 45:16And despite the fact that absolutely all
  1358. 45:18agents work with worktrees, git worktree
  1359. 45:21, without problems, they still often
  1360. 45:23don't do it by default.
  1361. 45:25That is, if you don't have it saved in
  1362. 45:27memory anywhere or haven't explicitly
  1363. 45:29told it to, I often notice this because
  1364. 45:30, for example, I launched these four new
  1365. 45:32big projects, including this "vivi" one
  1366. 45:34that I'll describe to you now.
  1367. 45:36When I tried to build some features that
  1368. 45:37way, it immediately started creating
  1369. 45:39branches.
  1370. 45:40So it's still clear that if you start
  1371. 45:41completely from scratch and it isn't
  1372. 45:43trained, you have to teach it to use
  1373. 45:44worktrees. Well, worktrees allow you to
  1374. 45:46not overlap by using separate folders.
  1375. 45:47Each works in its own environment. But
  1376. 45:49there are, again, tools that allow you
  1377. 45:51to manage these worktrees. People
  1378. 45:53started recommending things to me like,
  1379. 45:55check this out, check that out. In the
  1380. 45:56end, I sat down with an IDE and realized
  1381. 45:58that none of these things suited me or
  1382. 45:59were even necessary in general. And
  1383. 46:01there is a problem there. What kind?
  1384. 46:03Even if you have a tool that knows how
  1385. 46:04to create these worktrees, that's not
  1386. 46:06the point. The point is what gets
  1387. 46:07launched inside, and that is your logic
  1388. 46:09. No tool is going to solve that for you
  1389. 46:11. If we take typical web projects again
  1390. 46:13, what appears there immediately? You
  1391. 46:15need to start the project, right,
  1392. 46:16there's the database, and then you have
  1393. 46:18ports. Accordingly, if you don't do
  1394. 46:20anything special, the ports will be the
  1395. 46:23same. Meaning, if something started in
  1396. 46:25one worktree, it will crash in another,
  1397. 46:27well, because it can't spin up. Take
  1398. 46:29running tests, for example, because if
  1399. 46:31you have, say, five agents in a PT Work
  1400. 46:333 running tests simultaneously, that's
  1401. 46:35it—you're done for, everything will
  1402. 46:37grind to a halt. Then, as a rule, even
  1403. 46:39if you have a fairly advanced system,
  1404. 46:41not only does it run in Work 3, but it
  1405. 46:44can also launch several agents in
  1406. 46:46parallel that diverge in various ways,
  1407. 46:48which in turn leads to even more
  1408. 46:50increasing load. Then, even if you've
  1409. 46:52set up Work 3, you still need to install
  1410. 46:54dependencies there, for example.
  1411. 46:55And if you have, say, some kind of
  1412. 46:57module, it might happen that each Work 3
  1413. 46:59starts gobbling up 5-10 GB of space.
  1414. 47:02So, despite the fact that we have
  1415. 47:04mega-powerful machines now—the latest
  1416. 47:06Macs are just out of this world—you
  1417. 47:08suddenly find yourself in a situation
  1418. 47:10where everything starts to lag, you run
  1419. 47:12out of memory, the disk fills up, and
  1420. 47:14everything locks up.
  1421. 47:16And, having long forgotten about such
  1422. 47:18problems when I was writing code myself
  1423. 47:20before reaching high levels of
  1424. 47:21parallelization, I ended up in a
  1425. 47:23situation where I have to clear my disk
  1426. 47:25every day. I have 500 GB, but those 200
  1427. 47:27that fluctuate, they just get eaten up
  1428. 47:29in 3 days, especially with some boom,
  1429. 47:32you free it up, and you're already down
  1430. 47:34a gigabyte.
  1431. 47:35Yeah.
  1432. 47:37And so, in addition to starting to use
  1433. 47:39Work 3, the task emerged to use a large
  1434. 47:41number of mechanics that allow for
  1435. 47:43working effectively with these Work 3s
  1436. 47:46and projects.
  1437. 47:48And when I wrote a post about this
  1438. 47:49recently, it turned out that a lot of
  1439. 47:51people are currently facing the exact
  1440. 47:52same pitfalls and are trying to solve
  1441. 47:53them.
  1442. 47:54And as practice shows, they are solving
  1443. 47:56them in exactly the same way I described
  1444. 47:57.
  1445. 47:57Well, because overall this isn't some
  1446. 47:59new story, but it is very actively
  1447. 48:01occupying the minds of most developers.
  1448. 48:04For those who have a job right now, a
  1449. 48:06little disclaimer. So, what does that
  1450. 48:09include? Let's go in order. First, for
  1451. 48:11example, is assigning random ports,
  1452. 48:14because it needs to run in parallel. And
  1453. 48:17I just assigned this to an agent; it
  1454. 48:18wrote the necessary scripts for me and
  1455. 48:20used the right utilities. It’s basically
  1456. 48:22the simplest part of the whole story,
  1457. 48:23right, assigning random ports.
  1458. 48:25Especially if you use something like
  1459. 48:27Mesos, which handles the substitution,
  1460. 48:29it also intelligently distributes it
  1461. 48:31across all the components.
  1462. 48:32Second is the database. So, first of all
  1463. 48:36, if I were using Docker Compose, I’d be
  1464. 48:39overwhelmed by having a separate compose
  1465. 48:42instance starting up for every single
  1466. 48:45project. It’s a pretty heavy thing, no
  1467. 48:47matter how you look at it. Especially on
  1468. 48:48a Mac. That’s why I just run a plain
  1469. 48:50Postgres instance instead. It starts up
  1470. 48:53once, and each project creates its own
  1471. 48:55database inside. It just so happens that
  1472. 48:57I’m using the latest Postgres everywhere
  1473. 48:59, but even if there were different
  1474. 49:00versions, well, okay, maybe a couple
  1475. 49:01would run.
  1476. 49:02So, I manage things by simply creating
  1477. 49:04databases. But the DBMS instance itself
  1478. 49:07is singular.
  1479. 49:08This also applies if any other heavy
  1480. 49:10components show up; they can be unified
  1481. 49:12in this way so they’re reused.
  1482. 49:14At the same time, nothing will conflict
  1483. 49:16because, well, the databases inside are
  1484. 49:18separate.
  1485. 49:19Now, the next thing is the actual
  1486. 49:21execution of heavy processes. And this
  1487. 49:23is interesting. It became obvious that
  1488. 49:25they needed to be ordered somehow. I
  1489. 49:26started looking for utilities that could
  1490. 49:28apply a lock.
  1491. 49:29Instead of just running "make test" or,
  1492. 49:32in this case, "ztest"—yes, that’s what I
  1493. 49:34run—I wanted something that locks the
  1494. 49:37execution, checks the logs to see what
  1495. 49:39else is running, and waits its turn.
  1496. 49:42There are several different utilities.
  1497. 49:44One of them is "flock," for example, but
  1498. 49:46it turned out it doesn't work that well
  1499. 49:47on Mac or everywhere else. At first, he
  1500. 49:49just threw together a bunch of scripts
  1501. 49:51for me. And when I realized I needed
  1502. 49:52this in three or four different projects
  1503. 49:53, I thought, "This is kind of ridiculous
  1504. 49:55." Why hasn't anyone written this yet?
  1505. 49:57What did I do? I basically said, "
  1506. 49:59Alright, enough, let's just write it."
  1507. 50:01He actually came up with the name
  1508. 50:02himself. I really liked this "heavy"
  1509. 50:04idea. I said, "Let's do it, I don't have
  1510. 50:05anything in Rust anyway." So, we banged
  1511. 50:07out this thing in Rust. I included a
  1512. 50:10link to it, by the way, in that post.
  1513. 50:12Take note, it already has 35 stars. A
  1514. 50:13whole bunch of people used it and said
  1515. 50:15they were really happy with it.
  1516. 50:17Basically, the utility is as simple as a
  1517. 50:19brick to use. We place it before any
  1518. 50:21execution.
  1519. 50:22After that, it runs the command you need
  1520. 50:24; it’s very cool and highly configurable
  1521. 50:27.
  1522. 50:27So, it doesn't just lock; it has slots.
  1523. 50:30Meaning you can specify that, for
  1524. 50:31example, three are allowed in parallel.
  1525. 50:33And the slots aren't global, but rather
  1526. 50:34for specific types of tasks. Meaning you
  1527. 50:36can also create different pools. In
  1528. 50:38general, there are quite a lot of such
  1529. 50:40settings there. Plus, by the way, for
  1530. 50:42example, something important and cool
  1531. 50:43that turned out to be missing everywhere
  1532. 50:45else is that it can handle nesting.
  1533. 50:47That is, if you have things running at
  1534. 50:49different stages and this appear at
  1535. 50:52different levels—which can easily happen
  1536. 50:54when there are many tasks combined into
  1537. 50:57higher-level tasks—it knows how to
  1538. 50:59aggregate them so it works with nested
  1539. 51:01processes.
  1540. 51:03And so on. In short, it's a very cool
  1541. 51:06tool. You can, of course, write your own
  1542. 51:08, or you can use this one. And right
  1543. 51:10here, he specifically wrote why use his
  1544. 51:12instead of other existing utilities. I
  1545. 51:15highly recommend it. You have the source
  1546. 51:18code, so you can take a look.
  1547. 51:20The utility is as fast and compact as
  1548. 51:21possible, tested, and can be used as a
  1549. 51:23library or installed however you want.
  1550. 51:25I've made all possible options available
  1551. 51:28, whether through Cargo, Homebrew, or
  1552. 51:30even just via binary—any way you like.
  1553. 51:32This is the first thing I made.
  1554. 51:34Again, I repeat, it's not about using
  1555. 51:36this specific library, but about
  1556. 51:38understanding the concept itself. I even
  1557. 51:40had an exchange with one person who said
  1558. 51:42, "I won't use it, I have my own project
  1559. 51:44, but I stole a couple of good ideas
  1560. 51:46from yours."
  1561. 51:48So we ended up exchanging a few ideas on
  1562. 51:50how such utilities are built.
  1563. 51:53Alright, let's move on. That covers
  1564. 51:55parallel execution. So, what else? Let
  1565. 51:59me talk about something called DB
  1566. 52:00Cleaner. It’s a bit of a surprise to me
  1567. 52:03that this doesn't exist in Go. I'll
  1568. 52:05explain the idea and concept now.
  1569. 52:09So, if we take so-called "Rich
  1570. 52:10Frameworks"—classic heavy frameworks
  1571. 52:13that grew out of an earlier era, like
  1572. 52:15Laravel, Rails, Spring Boot, or Django.
  1573. 52:19And the list goes on. In short, there
  1574. 52:21are these frameworks that are "
  1575. 52:22all-inclusive," doing everything from
  1576. 52:24start to finish.
  1577. 52:26And at some point—quite early, to be
  1578. 52:28fair, back in 2007 or even earlier—they
  1579. 52:31came up with the concept that it's great
  1580. 52:33to run tests within transactions.
  1581. 52:36Firstly, you don't need to wipe the
  1582. 52:38database, or you'd just get sick of
  1583. 52:39testing. Secondly, there’s no point in
  1584. 52:41doing that. Let's just start a
  1585. 52:42transaction at the beginning of the test
  1586. 52:44and roll it back at the end.
  1587. 52:45Consequently, you don't need to monitor
  1588. 52:47the data. It's incredibly fast. And it's
  1589. 52:49just generally great. I’ve been using
  1590. 52:51this approach my whole life.
  1591. 52:53Of course, you might also have something
  1592. 52:54like Redis, things that need to be
  1593. 52:56closed, and external requests—
  1594. 52:57everything is a bit more complex in real
  1595. 52:59life.
  1596. 52:59But at least for most projects, the key
  1597. 53:01story of how to interact with the
  1598. 53:03database is indeed solved in this exact
  1599. 53:05way.
  1600. 53:05You could, of course, ask about the
  1601. 53:07logic that needs to run after a commit.
  1602. 53:10You can work with that in reality.
  1603. 53:12There are complex transactions, and ways
  1604. 53:14to build such logic, and other
  1605. 53:16approaches, and so on.
  1606. 53:18But that remains outside the scope for
  1607. 53:19now. Right now, we are only talking
  1608. 53:21about the most core idea. In short,
  1609. 53:22despite the fact that the approach is
  1610. 53:24super popular and everyone who has
  1611. 53:26written in such frameworks knows about
  1612. 53:28it, in Go there are simply no solutions
  1613. 53:30—none at all—that do this. And when I
  1614. 53:32started this project, I immediately
  1615. 53:34asked it to generate this kind of thing
  1616. 53:35for me. It generated something, and the
  1617. 53:37tests were executed accordingly.
  1618. 53:39But again, I have three such projects in
  1619. 53:41Go, some private and two or three public
  1620. 53:44ones.
  1621. 53:45By the way, the Basic code has also been
  1622. 53:46rewritten in Go, and it has this too.
  1623. 53:48And I thought, "Alright, it's time to
  1624. 53:51extract it separately." At the same time
  1625. 53:53, when I first started extracting it, I
  1626. 53:54thought, "Okay, what do people talk
  1627. 53:56about most often here?""First of all,
  1628. 53:57let's try testcontainers." I thought, "
  1629. 53:59Well, let's try it and see if
  1630. 54:01testcontainers can solve anything, where
  1631. 54:03a container is spun up for each test and
  1632. 54:05then destroyed.""In general, it seems
  1633. 54:07like a beauty." And let's also try
  1634. 54:09another approach with templates. This
  1635. 54:11has become really popular now too. It
  1636. 54:13uses a copy-on-write technique, and you
  1637. 54:14create a kind of template inside the
  1638. 54:15database. Accordingly, it’s as if the
  1639. 54:17database is copied, though not entirely
  1640. 54:19. And then you can work with it. So it's
  1641. 54:21kind of like another approach. I asked
  1642. 54:23this thing to conduct some research. And
  1643. 54:26guess what it did for me? Well, the AI
  1644. 54:28showed me this kind of thing. It
  1645. 54:31analyzed, in short, how much time it
  1646. 54:34takes. I’ll fast forward here and show
  1647. 54:36you.
  1648. 54:38It turned out that the approach with
  1649. 54:39deletions and transactions is, well,
  1650. 54:41incredibly faster.
  1651. 54:43That is, compared to working with
  1652. 54:44templates. For some reason,
  1653. 54:45testcontainers aren't shown here, by the
  1654. 54:46way. Back then it showed me a similar
  1655. 54:48story there.
  1656. 54:49But templates and testcontainers,
  1657. 54:51despite seeming fast—I mean, what’s 50
  1658. 54:54milliseconds or 80 milliseconds, right?
  1659. 54:58Or with testcontainers, there was a
  1660. 55:00similar example, but compared to a
  1661. 55:01transaction that takes 3 milliseconds,
  1662. 55:03that is, excuse me, a lot.
  1663. 55:06Especially when we're talking about a
  1664. 55:08very, very large number of tests,
  1665. 55:09parallel runs, and everything else,
  1666. 55:11because you need to look a bit deeper
  1667. 55:13there; one thing is transactions,
  1668. 55:14another thing is all those templates and
  1669. 55:16testcontainers, which also involve
  1670. 55:18spinning up actual processes and so on.
  1671. 55:20Accordingly, the load increases not only
  1672. 55:22on the CPU, but on the overall context.
  1673. 55:24And what happens because of this? It's
  1674. 55:26that at high volumes, this becomes very
  1675. 55:29noticeable. In the end, even though I
  1676. 55:31initially thought: "Okay, fine, guys,
  1677. 55:33let's do it the way you're used to,
  1678. 55:34let's not use transactions, let's do it
  1679. 55:36differently." Even the AI itself—again,
  1680. 55:37it's not that it convinced me, it's just
  1681. 55:39that I discussed it with it for a long
  1682. 55:40time in detail. Besides, I do understand
  1683. 55:42a little bit about what I'm doing. I
  1684. 55:44came to the conclusion that if I take
  1685. 55:45any other path, I'll be digging my own
  1686. 55:47grave, especially as the number of tests
  1687. 55:49keeps growing. So, in the end, I built
  1688. 55:51this utility that works with SQL DB,
  1689. 55:53meaning it's universal and can connect
  1690. 55:56to anything. And it works on the
  1691. 55:58principle: start the test, roll it back
  1692. 55:59. This, by the way, is a port,
  1693. 56:01essentially, of database cleaner. There
  1694. 56:03is this thing in Ruby. It supports
  1695. 56:04various strategies there, including a
  1696. 56:06truncate strategy, which is also here.
  1697. 56:08You can, like, truncate instead of using
  1698. 56:10transactions, if anyone needs that. At
  1699. 56:12first, I named it PG Cleaner and built
  1700. 56:14it, but then I thought, why am I being
  1701. 56:16so dense? And so, I redesigned it. And
  1702. 56:18now this thing works, basically, as an
  1703. 56:20almost universal tool. Although, it
  1704. 56:22doesn't have all the databases yet.
  1705. 56:24SQLite, MySQL, MariaDB, Postgres. Well,
  1706. 56:26you can add more if needed. In short,
  1707. 56:28this thing can easily connect to your
  1708. 56:30project and allow you to do this. Again
  1709. 56:32, even if you—well, it's shown here,
  1710. 56:35everything works quite simply and easily
  1711. 56:37. You can take a look at the source code
  1712. 56:39, it's a small project, but the concept
  1713. 56:41itself is very important.
  1714. 56:43So, if you have a situation where it's
  1715. 56:45important to run tests quickly, I
  1716. 56:47generally recommend experimenting and
  1717. 56:49looking into testcontainers, templates,
  1718. 56:51and transaction commit-rollback cycles.
  1719. 56:54If you operate under the assumption that
  1720. 56:57you don't need any of this because you
  1721. 56:58just mock everything, then we’re just
  1722. 57:01not on the same page.
  1723. 57:02I’m of the opinion that you shouldn't
  1724. 57:04mock the database. Moving on. So, I made
  1725. 57:06another library, but it’s more of a
  1726. 57:08linter. A very interesting and unusual
  1727. 57:10linter that I essentially swiped from
  1728. 57:12Ruby. What's more, some of you have seen
  1729. 57:15my podcast with the creator of the
  1730. 57:17library I took this from. There's a
  1731. 57:19library there called
  1732. 57:21database_consistency.
  1733. 57:23It does a very interesting thing. It
  1734. 57:25looks at your database schema. That is,
  1735. 57:28you need to give it direct access to the
  1736. 57:29database, so it’s a bit trickier than a
  1737. 57:31regular linter. And then it compares
  1738. 57:33that against how your entities are
  1739. 57:34described in the code. And this can be—
  1740. 57:36well, in Ruby, everything is simple.
  1741. 57:38There’s like a single ORM in Rails,
  1742. 57:40which is Active Record. In Go, of course
  1743. 57:42, it's a bit more complex because there
  1744. 57:44are many tools you can use to work with
  1745. 57:46the database. In any case, there is some
  1746. 57:47sort of abstraction. It's not like
  1747. 57:48you’re just sending raw queries and
  1748. 57:50getting something back. Typically,
  1749. 57:51there’s some compilation, there are
  1750. 57:53structs, so all of that exists. And
  1751. 57:55that’s why it was a bit harder for me to
  1752. 57:57do this, but also a bit easier, because
  1753. 57:58again, an agent is doing it. And what
  1754. 58:00did I ask it to do? I said, "Let's do
  1755. 58:02this."
  1756. 58:03We need something that, following the
  1757. 58:06rules from database_consistency, takes
  1758. 58:08all the most modern approaches to
  1759. 58:10database interaction and can work
  1760. 58:12universally through adapters to compare
  1761. 58:15constraints in the database with
  1762. 58:17constraints in the code.
  1763. 58:19You might ask, "What kind of constraints
  1764. 58:20are these?""What could be the problem?"
  1765. 58:22"Well, there can be many problems." Here
  1766. 58:24, I’m showing a list of what’s included
  1767. 58:25. For example, when you have redundant
  1768. 58:28indexes, duplicate indexes, missing
  1769. 58:30uniqueness—for instance, it's present in
  1770. 58:33one place but not another.
  1771. 58:35Nullability, booleans, the use of
  1772. 58:38certain prefixes, mandatory vs. optional
  1773. 58:41fields, missed or unadded foreign keys,
  1774. 58:43and so on and so forth.
  1775. 58:46In short, a whole host of things that,
  1776. 58:47technically, could probably be expanded
  1777. 58:49further, but I’ve got about twenty rules
  1778. 58:51here that are being checked.
  1779. 58:53And despite the fact that, it would seem
  1780. 58:54, the ORMs there aren't that rich and
  1781. 58:56it's supposedly a bit easier to control
  1782. 58:58everything there, when I made this thing
  1783. 58:59and ran it, it immediately found flaws
  1784. 59:01in my new project.
  1785. 59:03So, accordingly, it fixed them, and now
  1786. 59:04, after that, it's controlled and it
  1787. 59:06doesn't happen anymore.
  1788. 59:07Accordingly, I'm happy, everyone's happy
  1789. 59:10, and I believe this project deserves to
  1790. 59:13be noticed and used more often.
  1791. 59:15But for now, since this is, so to speak
  1792. 59:17, my release and I'm talking about it
  1793. 59:19for the first time, I might see how it's
  1794. 59:21received and how often it gets used. So
  1795. 59:23it's quite possible that there will be
  1796. 59:25more expansion here if someone comes
  1797. 59:26along with their own stuff.
  1798. 59:28By the way, when I was building it, I
  1799. 59:30specifically asked for it to be written
  1800. 59:32in such a way that plugins for other
  1801. 59:33systems—since it doesn't cover
  1802. 59:35everything, right?
  1803. 59:37Maybe you've built something yourself in
  1804. 59:39your project for working with the
  1805. 59:40database—could be added, so it's easily
  1806. 59:42extensible.
  1807. 59:43Meaning you don't necessarily have to
  1808. 59:44submit a pull request here, although
  1809. 59:46that would be nice.
  1810. 59:47Instead, you can just create an
  1811. 59:49additional adapter for the specific
  1812. 59:51system you're using, and it will
  1813. 59:53accordingly check all this stuff.
  1814. 59:55Out of the box, it works with ent, bun,
  1815. 59:58and gorm. There’s serif here too, I
  1816. 1:00:00think, by the way. You can open the
  1817. 1:00:02adapter folder and see how many there
  1818. 1:00:03are. Bun next. Bun and G. Gorm next
  1819. 1:00:07static model.
  1820. 1:00:09In short, five or six adapters.
  1821. 1:00:12So that's the kind of thing it is. By
  1822. 1:00:13the way, there's already a pull request
  1823. 1:00:14here. Let's take a look at this pull
  1824. 1:00:15request from, probably, dependabot. Ah,
  1825. 1:00:17yes, it's a release. There were just
  1826. 1:00:19some changes there. It's suggesting I
  1827. 1:00:20release it. And the last thing I want to
  1828. 1:00:23talk about right now is, so to speak,
  1829. 1:00:25the pinnacle of these "dev quality gates
  1830. 1:00:27," which is called "pass"; when we were
  1831. 1:00:29choosing the word, my IDE even told me
  1832. 1:00:32that it's a word that even natives don't
  1833. 1:00:34really know.
  1834. 1:00:35It's like a pass for access to some
  1835. 1:00:38territory.
  1836. 1:00:39And it's really cool because it's easy
  1837. 1:00:41to read, easy to write, easy to
  1838. 1:00:43understand, and at the same time, it
  1839. 1:00:45describes well what it is.
  1840. 1:00:47So, look, an approach has become popular
  1841. 1:00:49now where we decide to write a linter
  1842. 1:00:51that specifically checks architectural
  1843. 1:00:54rules. Architectural rules—well, what
  1844. 1:00:55can be included in those? For example,
  1845. 1:00:57primarily the dependencies between
  1846. 1:00:59modules and components. Who can go where
  1847. 1:01:01, who can look at what, who can use what
  1848. 1:01:03and where.
  1849. 1:01:04The complexity of this thing lies in the
  1850. 1:01:06fact that it needs to have access to the
  1851. 1:01:08runtime. I mean, it's not enough for it
  1852. 1:01:10to just, well, basically access types.
  1853. 1:01:12It's not, it's not enough. Wait, I'm
  1854. 1:01:14slightly wrong here. Ideally, it needs
  1855. 1:01:16runtime, but at the very least, it needs
  1856. 1:01:19type information that an AST simply
  1857. 1:01:22cannot provide.
  1858. 1:01:24Meaning, if you use the same ast-grep I
  1859. 1:01:26mentioned earlier, where it can break
  1860. 1:01:28down any language into a tree for you,
  1861. 1:01:30and then you add your own rules.
  1862. 1:01:33First of all, those rules still can't be
  1863. 1:01:35very deeply nested. For example, this
  1864. 1:01:37thing can be used here, but this thing
  1865. 1:01:39can't. Secondly, it lacks type
  1866. 1:01:40information because, for example,
  1867. 1:01:42there's basic type inference, and it
  1868. 1:01:44doesn't always understand everything, so
  1869. 1:01:46we needed a tool that can handle that.
  1870. 1:01:47And someone might say, "Kirill, such
  1871. 1:01:49tools already exist." And it's true,
  1872. 1:01:50they do exist for some languages. There
  1873. 1:01:52are actually very few of them, but they
  1874. 1:01:53exist. I mean, for example, for Go
  1875. 1:01:54there's this, for Ruby there's that, and
  1876. 1:01:56so on.
  1877. 1:01:58And they try to describe things like: I
  1878. 1:02:00have these specific layers, they are in
  1879. 1:02:02these folders, with certain naming
  1880. 1:02:03conventions, who can depend on whom and
  1881. 1:02:05who can't, often with very tricky
  1882. 1:02:07configurations—for instance, something
  1883. 1:02:09might be allowed directly in tests, but
  1884. 1:02:11not here.
  1885. 1:02:12For example, SQL queries aren't allowed
  1886. 1:02:14directly here, but there's an exception
  1887. 1:02:15, so it's allowed there. So, there are
  1888. 1:02:17quite complex dependencies and intricate
  1889. 1:02:19rules for how this all works. And as you
  1890. 1:02:21can imagine, riding the wave of starting
  1891. 1:02:23all this, I thought, well, there isn't
  1892. 1:02:25really one great universal tool yet.
  1893. 1:02:27Is it even possible to create one?
  1894. 1:02:29At first, I built it based on ast-grep,
  1895. 1:02:31but it immediately showed me—well, it
  1896. 1:02:33was obvious—that you can't verify truly
  1897. 1:02:35proper, robust rules through it. I
  1898. 1:02:37thought, well then, this tool is useless
  1899. 1:02:40, because in that case, one could just
  1900. 1:02:42use ast-grep directly.
  1901. 1:02:45So I started looking for options,
  1902. 1:02:46wondering if it's possible to make it a
  1903. 1:02:48universal utility that can still get the
  1904. 1:02:50necessary info.
  1905. 1:02:51And you know what I found? I'll show you
  1906. 1:02:53right now.
  1907. 1:02:54It turns out there’s this thing called
  1908. 1:02:57the Code Intelligence Protocol.
  1909. 1:02:59I had no idea about it at all. It's a
  1910. 1:03:01fairly new thing. It's pronounced "skip
  1911. 1:03:03," and it describes itself as a Language
  1912. 1:03:05Agnostic Protocol for indexing source
  1913. 1:03:07code. It's used for things like go to
  1914. 1:03:09definition, find reference, and so on.
  1915. 1:03:11It's a standardized, unified format. It
  1916. 1:03:13turned out that many tools are already
  1917. 1:03:15using this gizmo. So, I must have really
  1918. 1:03:18missed out on this. And, as you can see
  1919. 1:03:20, it essentially solves the problem I
  1920. 1:03:22need addressed.
  1921. 1:03:24I mean, it does require various
  1922. 1:03:25compilers and such, but at least it can
  1923. 1:03:27be run in a somewhat universal way.
  1924. 1:03:30Anyway, I connected this thing and
  1925. 1:03:31rewrote it; the first version was based
  1926. 1:03:33on grep, and I rewrote it using this,
  1927. 1:03:35then added quite a few languages that I
  1928. 1:03:37didn't have initially.
  1929. 1:03:39I'll list the languages connected here.
  1930. 1:03:41Take a look. Go, TypeScript, Python,
  1931. 1:03:43Java, R, C#, Ruby, Kotlin, PHP, Swift.
  1932. 1:03:45There. And it states what is available
  1933. 1:03:47for each language. Notice the absolutely
  1934. 1:03:49giant README that describes all its
  1935. 1:03:51capabilities. I mean, I 100%tried to
  1936. 1:03:54make it that way. I did a deep research
  1937. 1:03:56session where I took all similar tools,
  1938. 1:03:58all similar feature requests, all
  1939. 1:04:00articles on the topic, and shoved in
  1940. 1:04:02every possible thing that could go in
  1941. 1:04:04there. And just so you understand, it
  1942. 1:04:06wasn't just a "let's throw it in" idea.
  1943. 1:04:08Roughly speaking, I was working on this
  1944. 1:04:10project in parallel with several others
  1945. 1:04:12, including Sflcon and Hexlet.
  1946. 1:04:15I'd send it over and say, "Look, your
  1947. 1:04:16rules state how things should be,
  1948. 1:04:18because I've accumulated a lot of rules
  1949. 1:04:20on how to code over this time."
  1950. 1:04:23I'd say, "Look at which problems this
  1951. 1:04:24can convert into automated checks for
  1952. 1:04:26you."
  1953. 1:04:27And they'd be like, "Oh, for instance, I
  1954. 1:04:28can enforce these five rules using this
  1955. 1:04:30thing." I do the same in another project
  1956. 1:04:32. "Oh, I can use these rules." But they
  1957. 1:04:34would reply: "First off, look, this part
  1958. 1:04:36is inconvenient because there are
  1959. 1:04:38exceptions, then I can't port this rule
  1960. 1:04:39, and so on." And I had a session with
  1961. 1:04:41probably five or six back-and-forth
  1962. 1:04:43exchanges. Until I reached a point where
  1963. 1:04:45the majority of their rules and how they
  1964. 1:04:47wanted to express them could indeed be
  1965. 1:04:49expressed. And, in principle, it no
  1966. 1:04:50longer made sense to be involved in it
  1967. 1:04:52manually.
  1968. 1:04:53Basically, I just started connecting it
  1969. 1:04:55to the projects I'm involved in and
  1970. 1:04:57stating that any rules that can be
  1971. 1:04:59expressed through this thing should be.
  1972. 1:05:01It looks, as you can see, like this.
  1973. 1:05:03So, it describes the layers, the rules,
  1974. 1:05:06who can depend on whom, and who cannot.
  1975. 1:05:09Uh, well, obviously there are excludes
  1976. 1:05:11and so on, the rules.
  1977. 1:05:13In short, a billion different kinds of
  1978. 1:05:15dependencies.
  1979. 1:05:17And the number of rules here is probably
  1980. 1:05:19about 15, if I'm not mistaken, checking
  1981. 1:05:21what is happening.
  1982. 1:05:23Yeah.
  1983. 1:05:24Yes, for instance, who can import a
  1984. 1:05:26component, defining layers and forbidden
  1985. 1:05:28dependencies. Overall, I'll be honest, I
  1986. 1:05:31liked it so much. I hope that this thing
  1987. 1:05:34becomes super popular. I will develop it
  1988. 1:05:36and use it to the max, because out of
  1989. 1:05:38everything I have, this is probably the
  1990. 1:05:40highest level of abstraction I’ve
  1991. 1:05:42managed to achieve, which enforces very
  1992. 1:05:44high-level rules. After I connected a
  1993. 1:05:46certain amount, despite the fact that I
  1994. 1:05:48was monitoring it overall, one still
  1995. 1:05:49needs to understand the difference
  1996. 1:05:51between automatic checks and the
  1997. 1:05:52recommendations or descriptions found in
  1998. 1:05:54your agency, MD, and other configs. So,
  1999. 1:05:56even though I monitor this very closely
  2000. 1:05:58and there were many rules, once I
  2001. 1:05:59connected this thing, it immediately
  2002. 1:06:01found hundreds of errors in different
  2003. 1:06:03places. Well, simply because when the
  2004. 1:06:05code exceeds a hundred thousand lines,
  2005. 1:06:06it's hard to keep track of everything,
  2006. 1:06:08and after that, it became easier to
  2007. 1:06:09rework.
  2008. 1:06:11Another issue is that when I switched to
  2009. 1:06:13this skip mechanism, this parsing
  2010. 1:06:15protocol, and expanded it to everything
  2011. 1:06:17possible, even though it's written
  2012. 1:06:19efficiently—I believe it's all written
  2013. 1:06:21in Rust—it still started working slowly
  2014. 1:06:23, just purely because all of this takes
  2015. 1:06:26time.
  2016. 1:06:27That is why, at some point, I simply
  2017. 1:06:29moved this check out of, you know where
  2018. 1:06:31?
  2019. 1:06:32So, it’s not in my regular make check,
  2020. 1:06:34which runs with every change, but I
  2021. 1:06:35moved it to a nightly check instead.
  2022. 1:06:38Meaning the rules themselves still exist
  2023. 1:06:40, and it keeps track of them in terms of
  2024. 1:06:41meaning, like an IDE. But the formal
  2025. 1:06:43check itself, to see that there's
  2026. 1:06:45nothing in the code, I run it at night,
  2027. 1:06:47and accordingly, all the changes that
  2028. 1:06:49came in are fixed after that. Anyway,
  2029. 1:06:51that’s the kind of gadget I ended up
  2030. 1:06:52with. And it, like my other tools and
  2031. 1:06:55like this printer, has a concept of a
  2032. 1:06:57baseline. I’ll explain for those who
  2033. 1:06:59don’t know how this is structured in
  2034. 1:07:00modern linters, again. So, when you
  2035. 1:07:02install this thing on a new project, it
  2036. 1:07:03will most likely show you billions of
  2037. 1:07:05errors if you describe everything you
  2038. 1:07:07want, right?
  2039. 1:07:08And there is a concept called a baseline
  2040. 1:07:10, where you run it and say, "this is the
  2041. 1:07:12baseline," so it decides that we won't
  2042. 1:07:14show these errors because we need to
  2043. 1:07:15start from scratch; otherwise, it’s very
  2044. 1:07:17hard to set up and follow when
  2045. 1:07:19everything is full of errors, right?
  2046. 1:07:21So, at least the checks would pass.
  2047. 1:07:23Accordingly, it generates a special file
  2048. 1:07:25where it describes all of this as
  2049. 1:07:26exceptions. And then, essentially, you
  2050. 1:07:29just need to request a separate task or
  2051. 1:07:31run an agent that takes this baseline
  2052. 1:07:33file, removes those exclusions bit by
  2053. 1:07:36bit, and fixes the code this way until
  2054. 1:07:38everything is resolved. So, this is a
  2055. 1:07:40very cool mechanic in all modern
  2056. 1:07:42verification systems that allows you to
  2057. 1:07:44connect it without worrying about the
  2058. 1:07:45thousands of errors you have, waiting
  2059. 1:07:47for them all to turn green before you
  2060. 1:07:49can finish. That's the kind of thing it
  2061. 1:07:51is.
  2062. 1:07:51By the way, when I was talking, I forgot
  2063. 1:07:54to mention something else, you know what
  2064. 1:07:56kind of thing exists. While I was
  2065. 1:07:58looking for all these tools, I found a
  2066. 1:08:00cool tool, for example. You'll find it
  2067. 1:08:02in the dev quality gates; it looks at
  2068. 1:08:05your Open API and sees the changes
  2069. 1:08:07you've made, let's say in a new release
  2070. 1:08:09, and checks, for example, for backward
  2071. 1:08:12compatibility violations. If there are
  2072. 1:08:14any, it won't let it pass. How do you
  2073. 1:08:16like that? I probably wouldn't have
  2074. 1:08:17thought about it that way, or at least
  2075. 1:08:19it wouldn't have occurred to me until it
  2076. 1:08:21was suggested. Well, perhaps, again,
  2077. 1:08:23because the project is still young and
  2078. 1:08:25we haven't reached production yet—we’re
  2079. 1:08:27still in the process, especially with
  2080. 1:08:29our design-first approach.
  2081. 1:08:31But overall, I think there will be
  2082. 1:08:33plenty of new ideas and concepts,
  2083. 1:08:35especially if people notice them and
  2084. 1:08:37pull them from different languages,
  2085. 1:08:39because different languages have various
  2086. 1:08:42cool gadgets that will ultimately allow
  2087. 1:08:44you to wrap everything up like this and
  2088. 1:08:46force the project to follow a large
  2089. 1:08:48number of formal rules, and generally
  2090. 1:08:50move many things to a formal level.
  2091. 1:08:54Well, guys, that's probably about the
  2092. 1:08:55story I wanted to tell today. Thank you
  2093. 1:08:57all very much. I hope it was interesting
  2094. 1:08:59and useful.
  2095. 1:09:00Be sure to write in the comments what
  2096. 1:09:02new things you learned, what you applied
  2097. 1:09:04, how it helped you, or any new tricks I
  2098. 1:09:06didn't mention that you think everyone
  2099. 1:09:08should know about.
  2100. 1:09:10I will definitely read them, check them
  2101. 1:09:11out, add to them if needed, and give
  2102. 1:09:12them a like. And, of course, send over a
  2103. 1:09:14pull request. So, until next time. Bye
  2104. 1:09:17everyone.
  2105. 1:09:23Hey

About this transcript

This page contains the full transcript of Как контролировать код ИИ-агентов: Quality Gates, архитектура и инструменты разработчика by Организованное программирование | Кирилл Мокевнин, generated from the public captions YouTube serves with the video. The transcript has 13,481 words across 2,105 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to choose a caption track available on the video.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, caption language selection, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.