<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Aleksei Lobanov</title>
  <subtitle type="text">Personal blog of Aleksei Lobanov</subtitle>
  <id>https://lobanov-av.ru/feed.xml</id>
  <link rel="self" type="application/atom+xml" href="https://lobanov-av.ru/feed.xml"/>
  <link rel="alternate" type="text/html" hreflang="en-US" href="https://lobanov-av.ru/"/>
  <updated>2026-08-16T00:00:00+00:00</updated>
  <generator uri="https://jekyllrb.com/">Jekyll</generator>
  <author>
    <name>Lobanov Aleksei</name>
  </author>
  <entry>
    <title type="html">Good Luck, Have Fun, Don&apos;t Die</title>
    <id>https://lobanov-av.ru/logs/2026-08-16-good-luck-have-fun-dont-die-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-08-16-good-luck-have-fun-dont-die-movie-log.html"/>
    <published>2026-08-16T00:00:00+00:00</published>
    <updated>2026-08-16T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🔁 Time Loop"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-08-16-good-luck-have-fun-dont-die-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Verbinski is back after ten years, and it’s &lt;strong&gt;not a great comeback&lt;/strong&gt;. A man from the future keeps replaying the same night in a diner to stop a rogue AI. &lt;strong&gt;I love time loop movies&lt;/strong&gt;, and this loop works. &lt;strong&gt;Rockwell carries the whole film&lt;/strong&gt; — you feel it when he is off screen. Then the ending goes into &lt;strong&gt;ugly CGI that looks AI-generated&lt;/strong&gt;. Fun once, no more.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Anatomy of a Prompt</title>
    <id>https://lobanov-av.ru/2026/08/13/terminal-setup.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/2026/08/13/terminal-setup.html"/>
    <published>2026-08-13T00:00:00+00:00</published>
    <updated>2026-08-13T00:00:00+00:00</updated>
    <category term="Tools"/>
    <summary type="html">A line-by-line guide to my terminal setup — what every segment of the prompt means, how it is built, and what it costs.</summary><content type="html" xml:base="https://lobanov-av.ru/2026/08/13/terminal-setup.html">&lt;style&gt;
.lang-toggle {
  position: absolute;
  top: 15px;
  right: 18px;
  display: flex;
  gap: 6px;
}
.lang-btn {
  font-family: var(--code-font);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 12px;
  border-radius: 8px;
  border: 1px solid var(--border-color);
  background-color: var(--background-color-light);
  color: var(--primary-color);
  cursor: pointer;
  margin: 0;
  transition: background-color 0.2s ease;
}
.lang-btn.active {
  background-color: var(--secondary-color);
  color: var(--background-color);
  border-color: var(--secondary-color);
}
.terminal-shot {
  display: block;
  width: 100%;
  border-radius: 10px;
  border: 1px solid var(--border-color);
  background-color: #0f1419;
  margin: 0;
}
.terminal-shot-caption {
  display: block;
  font-family: var(--code-font);
  font-size: 12px;
  opacity: 0.6;
  margin-top: 8px;
}
&lt;/style&gt;

&lt;div class=&quot;lang-toggle&quot;&gt;
  &lt;button class=&quot;lang-btn active&quot; onclick=&quot;setLang(&apos;en&apos;)&quot;&gt;EN&lt;/button&gt;
  &lt;button class=&quot;lang-btn&quot; onclick=&quot;setLang(&apos;ru&apos;)&quot;&gt;RU&lt;/button&gt;
&lt;/div&gt;

&lt;div id=&quot;lang-en&quot;&gt;

  &lt;hr /&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Every time someone sees my terminal over a screen share, the same question comes up: &lt;em&gt;“what is that prompt?”&lt;/em&gt;. So here is the whole thing — every segment, what produces it, and how to rebuild it from scratch.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;This is what it looks like inside a repository:&lt;/p&gt;

  &lt;figure&gt;
  &lt;img src=&quot;/assets/img/terminal-prompt.png&quot; alt=&quot;Terminal prompt showing a blue directory block reading risk, a yellow git branch block reading master, git status [!?] and metrics +1 -32, with Node and Docker context right-aligned, and the git email on a second line&quot; class=&quot;terminal-shot&quot; /&gt;
  &lt;figcaption class=&quot;terminal-shot-caption&quot;&gt;Ghostty · ayu · JetBrains Mono Nerd Font · Starship&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Nine pieces of information, none of which I had to ask for. Where I am, which branch, that the working tree is dirty and has untracked files, that I am one commit ahead in additions and thirty-two in deletions, which Node version this project uses, which Docker context is active, and — critically — &lt;strong&gt;which git identity I am committing as&lt;/strong&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;That last one is not vanity. It is the reason the second line exists at all.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;the-stack&quot;&gt;The Stack&lt;/h2&gt;

  &lt;p&gt;Four independent layers. You can adopt any one of them without the others.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Layer&lt;/th&gt;
        &lt;th&gt;Tool&lt;/th&gt;
        &lt;th&gt;What it does&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Terminal&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Ghostty&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;Window, colours, transparency, font rendering&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Font&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;JetBrains Mono Nerd Font&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;The glyphs — without it you get boxes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Prompt&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Starship&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;Everything you see before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;❯&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Shell tooling&lt;/td&gt;
        &lt;td&gt;atuin, zoxide, fzf, eza, yazi&lt;/td&gt;
        &lt;td&gt;History, navigation, listing, file browsing&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Install all of it in one go:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; ghostty font-jetbrains-mono-nerd-font
brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;starship atuin zoxide fzf eza yazi&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;layer-1--the-terminal&quot;&gt;Layer 1 — The Terminal&lt;/h2&gt;

  &lt;p&gt;Ghostty is a GPU-accelerated terminal written by Mitchell Hashimoto. It is fast, it is native on macOS, and — the part that matters here — it is configured by a plain text file rather than a settings panel.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The config lives at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Application Support/com.mitchellh.ghostty/config&lt;/code&gt; on macOS (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/ghostty/config&lt;/code&gt; if you prefer XDG). Mine, in full:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;py&quot;&gt;theme&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ayu&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;24&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-balance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-family&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Medium&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-bold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Bold&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-italic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Medium Italic&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-bold-italic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Bold Italic&quot;&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-decoration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;background-opacity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.85&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;background-blur-radius&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;27&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-thicken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;shell-integration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;detect&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;shell-integration-features&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sudo,no-cursor&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;cursor-style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bar&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;cursor-style-blink&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mouse-hide-while-typing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;confirm-close-surface&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-icon&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;retro&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-icon-frame&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aluminum&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-window-shadow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;A few of these earn their place more than others:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window-padding-x = 24&lt;/code&gt;&lt;/strong&gt; — the single highest-impact line in the file. Text pinned to the window edge reads as cramped; 24px of breathing room does more for legibility than any colour scheme.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-opacity&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-blur-radius&lt;/code&gt;&lt;/strong&gt; — translucency without the blur is unreadable noise. The two go together or not at all.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell-integration = detect&lt;/code&gt;&lt;/strong&gt; — lets Ghostty know where prompts start and end, which is what makes scroll-to-previous-command work.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-thicken = true&lt;/code&gt;&lt;/strong&gt; — macOS renders thin fonts thinner than you expect. This compensates.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ghostty +show-config --default --docs&lt;/code&gt; to see every option with inline documentation. It is one of the better-documented configs I have worked with.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;layer-2--the-font&quot;&gt;Layer 2 — The Font&lt;/h2&gt;

  &lt;p&gt;This is the step people skip, and then nothing works.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The prompt uses glyphs — the powerline arrow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;, the git branch symbol&lt;/code&gt;, the Node hexagon &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;— that do not exist in normal fonts. A **Nerd Font** is a regular font with those glyphs patched in. Without one you get&lt;/code&gt; boxes where the icons should be.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; font-jetbrains-mono-nerd-font&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Then point the terminal at it. Note the name in my config is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JetBrainsMono NFM&lt;/code&gt; — &lt;strong&gt;NFM&lt;/strong&gt; is the &lt;em&gt;Nerd Font Mono&lt;/em&gt; variant, where the icons are squeezed into a single character cell. There is also plain &lt;strong&gt;NF&lt;/strong&gt;, where icons take up two cells. NFM keeps column alignment predictable; NF looks slightly better at large sizes. Pick one and be consistent.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;blockquote&gt;
    &lt;p&gt;If you are reading this article in a browser without a Nerd Font installed, some glyphs in the code blocks below will render as empty boxes. That is expected — they will look correct in your terminal.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;layer-3--the-prompt&quot;&gt;Layer 3 — The Prompt&lt;/h2&gt;

  &lt;p&gt;&lt;a href=&quot;https://starship.rs&quot;&gt;Starship&lt;/a&gt; is a single binary that renders the prompt. It is cross-shell, it is configured in one TOML file, and it detects context automatically — you do not tell it “this is a Node project”, it notices.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Hook it into zsh as the &lt;strong&gt;last&lt;/strong&gt; line of your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt;, after any theme framework:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;starship init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;If you use oh-my-zsh, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ZSH_THEME=&quot;&quot;&lt;/code&gt; so it does not fight Starship for the prompt.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;the-format-string-is-the-table-of-contents&quot;&gt;The format string is the table of contents&lt;/h3&gt;

  &lt;p&gt;Everything in Starship flows from one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;format&lt;/code&gt; key in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/starship.toml&lt;/code&gt;. Read it top to bottom and you have read the prompt:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;py&quot;&gt;add_newline&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command_timeout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[](fg:#3B76F0)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$directory&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.directory_separator_not_git}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.directory_separator_git}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$git_branch[](fg:#FCF392)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$git_commit$git_status$git_metrics$git_state$fill$cmd_duration$nodejs$all&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.git_config_email}
$character&quot;&quot;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Two mechanics to notice before the modules themselves:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;Trailing backslashes.&lt;/strong&gt; Each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt; joins the next line without a newline. It lets you write the format one module per line — otherwise this would be one unreadable 300-character string.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;The line break is literal.&lt;/strong&gt; There is exactly one real newline in that string, right before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$character&lt;/code&gt;. That is what puts the email on its own row and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;❯&lt;/code&gt; below it.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command_timeout = 2000&lt;/code&gt; matters because of the custom modules further down — they shell out, and the default 500ms timeout will make Starship complain on a cold filesystem cache.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;the-directory-block&quot;&gt;The directory block&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[directory]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;truncate_to_repo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ $path ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fg:#ffffff bg:#3B76F0&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;truncate_to_repo = true&lt;/code&gt; is the setting that makes this readable. Inside a repo it shows the repo name, not the eleven directories above it. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Development/work/clients/2026/risk-engine/apps/mobile&lt;/code&gt; becomes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;risk&lt;/code&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The background colour is set on the &lt;em&gt;style&lt;/em&gt;, not drawn separately — that is how you get a solid block rather than coloured text.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;the-powerline-trick&quot;&gt;The powerline trick&lt;/h3&gt;

  &lt;p&gt;This is the part of the config I am most pleased with and the part that is least obvious.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;A powerline separator is just the glyph `` painted with the previous block’s colour as &lt;strong&gt;foreground&lt;/strong&gt; and the next block’s colour as &lt;strong&gt;background&lt;/strong&gt;. Easy — except the colour that comes next depends on whether you are in a git repo. Inside a repo it is the yellow branch block; outside, it is nothing.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Starship has no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; statement. But &lt;strong&gt;custom modules have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;when&lt;/code&gt; condition&lt;/strong&gt;, and a custom module with an empty command is a pure conditional renderer:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[custom.directory_separator_git]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Separator after the directory when inside a git repository.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[](fg:#3B76F0 bg:#FCF392)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git rev-parse --is-inside-work-tree &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[custom.directory_separator_not_git]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Separator after the directory when NOT inside a git repository.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[](fg:#3B76F0)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;! git rev-parse --is-inside-work-tree &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Both sit in the format string next to each other. Exactly one ever renders. Inside a repo the arrow bridges blue into yellow; outside, it fades blue into the background. The seam is invisible either way.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Same trick, opposite end: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$git_branch[](fg:#FCF392)&lt;/code&gt; closes the yellow block back to the background, and that closing arrow is written inline in the format string rather than as its own module — it only ever renders when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$git_branch&lt;/code&gt; does.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;git-state&quot;&gt;Git state&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[git_branch]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ $symbol$branch(:$remote_branch) ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fg:#1C3A5E bg:#FCF392&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[git_metrics]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_metrics&lt;/code&gt; is &lt;strong&gt;off by default&lt;/strong&gt; and worth turning on — it is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+1 -32&lt;/code&gt; in the sample prompt, lines added and deleted since the last commit. It is the difference between knowing you have changes and knowing how big they are.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_status&lt;/code&gt; is on by default and needs no config. Its shorthand is worth memorising:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Symbol&lt;/th&gt;
        &lt;th&gt;Meaning&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;modified files&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;untracked files&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;staged changes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;stashed changes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⇡&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⇣&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;ahead / behind remote&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;merge conflict&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;So &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[!?] +1 -32&lt;/code&gt; reads as: modified and untracked files present, one line added, thirty-two removed.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;pushing-things-to-the-right&quot;&gt;Pushing things to the right&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[fill]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[cmd_duration]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;min_time&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2_000&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ ⏲︎ $duration ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;white&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill&lt;/code&gt; module expands to consume all remaining terminal width. Anything after it in the format string gets pushed to the right edge. That is how the Node version and Docker context end up right-aligned without any manual padding.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd_duration&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;min_time = 2000&lt;/code&gt; only appears when a command took longer than two seconds. Silent when it does not matter, informative when it does — which is the right default for almost every prompt segment.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;all--the-catch-all&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$all&lt;/code&gt; — the catch-all&lt;/h3&gt;

  &lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$all&lt;/code&gt; at the end of the format string is a wildcard: it renders every module not already mentioned explicitly. That is where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;via  v24.4.0&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;via 🐳 colima&lt;/code&gt; come from — I never configured a Node module or a Docker module. Starship detected a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and an active Docker context and said so.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Same for Python virtualenvs, Rust toolchains, Ruby versions, Kubernetes contexts, AWS profiles. It is the highest ratio of information to configuration in the whole file.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;If a language shows up that you do not care about, disable it individually:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[ruby]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;the-second-line&quot;&gt;The second line&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[custom.git_config_email]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Output the current git user&apos;s configured email address.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git config user.email&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[$symbol(  $output)]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git rev-parse --is-inside-work-tree &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;This is the segment I would keep if I had to throw away the rest.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;If you work across a personal account and a work account, you will eventually commit to one with the identity of the other. You will notice weeks later, in a code review, on a branch that has already been merged. The fix is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config user.email&lt;/code&gt; per repository — but only if you remember to check, and nobody remembers to check.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;So the prompt checks. Every time. On its own line, in muted text, only inside repositories.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;layer-4--the-shell-around-it&quot;&gt;Layer 4 — The Shell Around It&lt;/h2&gt;

  &lt;p&gt;The prompt is what people notice. These are what I would actually miss.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;atuin--history-that-is-a-database&quot;&gt;atuin — history that is a database&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;atuin init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
bindkey &lt;span class=&quot;s1&quot;&gt;&apos;^R&apos;&lt;/span&gt; atuin-search
bindkey &lt;span class=&quot;s1&quot;&gt;&apos;^[[A&apos;&lt;/span&gt; atuin-search   &lt;span class=&quot;c&quot;&gt;# intercept the up arrow too&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Atuin replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zsh_history&lt;/code&gt; with a SQLite database and gives you a full-screen fuzzy search over it, filtered by directory, with exit codes and durations recorded. The second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindkey&lt;/code&gt; is the opinionated part: it hijacks the &lt;strong&gt;up arrow&lt;/strong&gt; as well, so the reflex you already have opens the good search instead of the bad one.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;zoxide--cd-that-learns&quot;&gt;zoxide — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt; that learns&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;zoxide init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Tracks which directories you actually visit and ranks them by frequency and recency. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z risk&lt;/code&gt; jumps to the risk-engine repo from anywhere. After a week of use you stop typing paths.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;fzf--fuzzy-finding-everywhere&quot;&gt;fzf — fuzzy finding everywhere&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;fzf &lt;span class=&quot;nt&quot;&gt;--zsh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;One line, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-T&lt;/code&gt; becomes a fuzzy file picker, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt-C&lt;/code&gt; a fuzzy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;. Many other tools use fzf as a backend, so installing it makes things you have not installed yet better.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;eza--ls-with-git-awareness&quot;&gt;eza — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt; with git awareness&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;eza --icons -l -F --colour=always -a --git --header --time-style=iso&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ee2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;eza --icons -l -TL 2 --total-size -F --colour=always&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--git&lt;/code&gt; annotates each file with its git status, which is the flag that makes eza worth the switch. The second alias is a two-level tree with directory sizes — the fastest way to answer “what is taking up space here”.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;yazi--a-file-manager-that-changes-your-shells-directory&quot;&gt;yazi — a file manager that changes your shell’s directory&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;y&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mktemp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;yazi-cwd.XXXXXX&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; cwd
	yazi &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cwd-file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;IFS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; cwd &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;builtin cd&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;A child process cannot change its parent’s working directory, so yazi writes its final directory to a temp file and the wrapper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;s there afterwards. Browse visually with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, quit, and the shell is already where you were looking.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;one-more-line-worth-stealing&quot;&gt;One more line worth stealing&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;precmd&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; print &lt;span class=&quot;nt&quot;&gt;-Pn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\e&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]0;%~&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\a&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Sets the terminal tab title to the current directory before each prompt. Trivial, and the difference between six identifiable tabs and six tabs labelled “zsh”.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;what-it-costs&quot;&gt;What It Costs&lt;/h2&gt;

  &lt;p&gt;Pretty prompts have a reputation for being slow, and this one is not free. Starship will tell you exactly how much:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;starship timings&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Measured in a real repository on my machine:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;custom.git_config_email             -  15ms
custom.directory_separator_git      -   8ms
custom.directory_separator_not_git  -   7ms
ruby                                -   5ms
git_metrics                         -   4ms
directory                           -   4ms
git_branch                          -  &amp;lt;1ms&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The three custom modules account for &lt;strong&gt;30ms of the roughly 45ms total&lt;/strong&gt; — two thirds of the cost, for one email address and one cosmetic arrow. Each of them spawns a process on every single prompt, and the two separator modules both run their check even though only one can ever render.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Modules run in parallel, so the wall-clock hit is smaller than the sum. At 45ms it stays under the threshold where a prompt feels sluggish, and I consider the git identity check worth it. But it is a real trade, and it is worth knowing which lines in your config you are paying for. If you want the aesthetics without the cost, drop the separator modules and accept a hard colour edge — you get 15ms back for a change most people would not notice.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;One more piece of honesty: my config carries a leftover &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$symbol&lt;/code&gt; in the format string. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol&lt;/code&gt; is not a module, so Starship silently renders nothing for it. It has been there for a year doing absolutely nothing. Check your own config with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;starship timings&lt;/code&gt; — anything that never appears in the output is not running.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;where-to-start&quot;&gt;Where to Start&lt;/h2&gt;

  &lt;p&gt;If you adopt one thing from this article, make it the Nerd Font and Starship with a default config — that is fifteen minutes and most of the visual payoff.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;If you adopt two, add atuin. Searchable history with directory context changes how you use a shell more than any prompt does.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The rest is decoration. Good decoration, tuned over a couple of years, and I would rebuild all of it on a new machine — but decoration.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;blockquote&gt;
    &lt;p&gt;One warning before you copy anyone’s dotfiles, mine included: check them for secrets first. API tokens exported in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt; are the single most common way a private repo becomes a public incident. Keep them in a secret manager and read them at runtime.&lt;/p&gt;
  &lt;/blockquote&gt;

&lt;/div&gt;

&lt;div id=&quot;lang-ru&quot; style=&quot;display: none&quot;&gt;

  &lt;hr /&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Каждый раз, когда кто-то видит мой терминал в шаринге экрана, звучит один и тот же вопрос: &lt;em&gt;«что это за промпт?»&lt;/em&gt;. Поэтому вот он целиком — каждый сегмент, что его порождает и как собрать всё с нуля.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Вот как это выглядит внутри репозитория:&lt;/p&gt;

  &lt;figure&gt;
  &lt;img src=&quot;/assets/img/terminal-prompt.png&quot; alt=&quot;Промпт терминала: синяя плашка директории risk, жёлтая плашка ветки master, статус git [!?] и метрики +1 -32, справа версия Node и Docker-контекст, на второй строке git-email&quot; class=&quot;terminal-shot&quot; /&gt;
  &lt;figcaption class=&quot;terminal-shot-caption&quot;&gt;Ghostty · ayu · JetBrains Mono Nerd Font · Starship&lt;/figcaption&gt;
&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Девять единиц информации, ни одну из которых не пришлось запрашивать. Где я, какая ветка, что рабочее дерево грязное и есть неотслеживаемые файлы, что добавлена одна строка и удалено тридцать две, какая версия Node в проекте, какой Docker-контекст активен и — самое важное — &lt;strong&gt;под какой git-личностью я коммичу&lt;/strong&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Последнее — не тщеславие. Именно ради него существует вторая строка.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section&quot;&gt;Стек&lt;/h2&gt;

  &lt;p&gt;Четыре независимых слоя. Любой можно взять отдельно от остальных.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Слой&lt;/th&gt;
        &lt;th&gt;Инструмент&lt;/th&gt;
        &lt;th&gt;Что делает&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;Терминал&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Ghostty&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;Окно, цвета, прозрачность, рендер шрифта&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Шрифт&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;JetBrains Mono Nerd Font&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;Глифы — без него будут квадраты&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Промпт&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;Starship&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;Всё, что видно до &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;❯&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Обвязка&lt;/td&gt;
        &lt;td&gt;atuin, zoxide, fzf, eza, yazi&lt;/td&gt;
        &lt;td&gt;История, навигация, листинг, файловый менеджер&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Установить всё разом:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; ghostty font-jetbrains-mono-nerd-font
brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;starship atuin zoxide fzf eza yazi&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-1&quot;&gt;Слой 1 — Терминал&lt;/h2&gt;

  &lt;p&gt;Ghostty — GPU-ускоренный терминал за авторством Митчелла Хашимото. Быстрый, нативный на macOS и — что здесь важнее всего — настраивается текстовым файлом, а не панелью настроек.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Конфиг лежит в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Library/Application Support/com.mitchellh.ghostty/config&lt;/code&gt; на macOS (или в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/ghostty/config&lt;/code&gt;, если предпочитаете XDG). Мой целиком:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ini&quot; data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;py&quot;&gt;theme&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ayu&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-x&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;24&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-y&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-padding-balance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-family&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Medium&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-bold&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Bold&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-italic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Medium Italic&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;font-family-bold-italic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;JetBrainsMono NFM Bold Italic&quot;&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-size&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;window-decoration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;background-opacity&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0.85&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;background-blur-radius&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;27&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;font-thicken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;shell-integration&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;detect&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;shell-integration-features&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;sudo,no-cursor&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;cursor-style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;bar&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;cursor-style-blink&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;mouse-hide-while-typing&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;confirm-close-surface&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-icon&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;retro&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-icon-frame&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;aluminum&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;macos-window-shadow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Несколько строк оправдывают себя больше остальных:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window-padding-x = 24&lt;/code&gt;&lt;/strong&gt; — самая полезная строка в файле. Текст, прижатый к краю окна, читается тесно; 24 пикселя воздуха дают для читаемости больше, чем любая цветовая схема.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-opacity&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-blur-radius&lt;/code&gt;&lt;/strong&gt; — прозрачность без блюра превращается в нечитаемый шум. Или вместе, или никак.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shell-integration = detect&lt;/code&gt;&lt;/strong&gt; — Ghostty начинает понимать, где начинается и заканчивается промпт, благодаря чему работает прыжок к предыдущей команде.&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-thicken = true&lt;/code&gt;&lt;/strong&gt; — macOS рендерит тонкие шрифты тоньше, чем ожидаешь. Это компенсирует.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ghostty +show-config --default --docs&lt;/code&gt; покажет все опции с документацией прямо в выводе. Один из лучше всего задокументированных конфигов, что мне попадались.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-2&quot;&gt;Слой 2 — Шрифт&lt;/h2&gt;

  &lt;p&gt;Этот шаг обычно пропускают, и дальше ничего не работает.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Промпт использует глифы — powerline-стрелку &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;, символ ветки&lt;/code&gt;, шестиугольник Node &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;— которых нет в обычных шрифтах. **Nerd Font** — это обычный шрифт с вшитыми в него этими глифами. Без него вместо иконок будут квадраты&lt;/code&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;brew &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cask&lt;/span&gt; font-jetbrains-mono-nerd-font&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Дальше указать его в терминале. Обратите внимание на имя в моём конфиге — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JetBrainsMono NFM&lt;/code&gt;, где &lt;strong&gt;NFM&lt;/strong&gt; это вариант &lt;em&gt;Nerd Font Mono&lt;/em&gt;: иконки ужаты в одну знакоместо. Есть ещё просто &lt;strong&gt;NF&lt;/strong&gt;, где иконки занимают две ячейки. NFM даёт предсказуемое выравнивание колонок, NF чуть красивее на крупных кеглях. Выберите один и держитесь его.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Если вы читаете статью в браузере без установленного Nerd Font, часть глифов в блоках кода отрисуется пустыми квадратами. Это ожидаемо — в терминале они будут выглядеть правильно.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-3&quot;&gt;Слой 3 — Промпт&lt;/h2&gt;

  &lt;p&gt;&lt;a href=&quot;https://starship.rs&quot;&gt;Starship&lt;/a&gt; — один бинарник, который рисует промпт. Работает с любой оболочкой, настраивается одним TOML-файлом и определяет контекст сам: не нужно говорить «здесь Node-проект», он это замечает.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Подключается &lt;strong&gt;последней&lt;/strong&gt; строкой в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt;, после любого фреймворка тем:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;starship init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Если используете oh-my-zsh — поставьте &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ZSH_THEME=&quot;&quot;&lt;/code&gt;, чтобы он не спорил со Starship за промпт.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;format---&quot;&gt;Строка format — это оглавление&lt;/h3&gt;

  &lt;p&gt;Всё в Starship вырастает из одного ключа &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;format&lt;/code&gt; в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.config/starship.toml&lt;/code&gt;. Прочитали его сверху вниз — прочитали весь промпт:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;py&quot;&gt;add_newline&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command_timeout&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;

&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[](fg:#3B76F0)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$directory&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.directory_separator_not_git}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.directory_separator_git}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$git_branch[](fg:#FCF392)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;$git_commit$git_status$git_metrics$git_state$fill$cmd_duration$nodejs$all&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;${custom.git_config_email}
$character&quot;&quot;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Две механики, которые стоит заметить раньше самих модулей:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;Обратные слэши в конце строк.&lt;/strong&gt; Каждый &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt; приклеивает следующую строку без переноса. Это позволяет писать format по модулю на строку — иначе получилась бы одна нечитаемая строка на 300 символов.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;Перенос строки — буквальный.&lt;/strong&gt; В этой строке ровно один настоящий перенос — прямо перед &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$character&lt;/code&gt;. Именно он выносит email на отдельный ряд, а &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;❯&lt;/code&gt; под него.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command_timeout = 2000&lt;/code&gt; нужен из-за кастомных модулей ниже: они запускают внешние процессы, и дефолтные 500 мс заставят Starship ругаться на холодном кеше файловой системы.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;section-4&quot;&gt;Блок директории&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[directory]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;truncate_to_repo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ $path ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fg:#ffffff bg:#3B76F0&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;truncate_to_repo = true&lt;/code&gt; — та самая настройка, которая делает блок читаемым. Внутри репозитория показывается имя репозитория, а не одиннадцать директорий над ним. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Development/work/clients/2026/risk-engine/apps/mobile&lt;/code&gt; превращается в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;risk&lt;/code&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Цвет фона задаётся в &lt;em&gt;стиле&lt;/em&gt;, а не рисуется отдельно — именно так получается сплошная плашка, а не просто цветной текст.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;powerline-&quot;&gt;Powerline-трюк&lt;/h3&gt;

  &lt;p&gt;Это та часть конфига, которой я доволен больше всего, и одновременно наименее очевидная.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Powerline-разделитель — это просто глиф ``, у которого &lt;strong&gt;цвет текста&lt;/strong&gt; равен цвету предыдущей плашки, а &lt;strong&gt;фон&lt;/strong&gt; — цвету следующей. Просто. Если бы не одно: цвет следующей плашки зависит от того, в репозитории вы или нет. Внутри — жёлтая ветка, снаружи — ничего.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;В Starship нет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt;. Зато у &lt;strong&gt;кастомных модулей есть условие &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;when&lt;/code&gt;&lt;/strong&gt;, а кастомный модуль с пустой командой — это чистый условный рендерер:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[custom.directory_separator_git]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Разделитель после директории внутри git-репозитория.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[](fg:#3B76F0 bg:#FCF392)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git rev-parse --is-inside-work-tree &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[custom.directory_separator_not_git]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Разделитель после директории вне git-репозитория.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[](fg:#3B76F0)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;! git rev-parse --is-inside-work-tree &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Оба стоят в format рядом друг с другом. Отрисуется ровно один. Внутри репозитория стрелка соединяет синий с жёлтым, снаружи — растворяет синий в фоне. Шов не виден ни там, ни там.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Тот же приём с другой стороны: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$git_branch[](fg:#FCF392)&lt;/code&gt; закрывает жёлтую плашку обратно в фон, и эта закрывающая стрелка написана прямо в строке format, а не отдельным модулем — так она отрисуется только тогда, когда отрисуется &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$git_branch&lt;/code&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;git&quot;&gt;Состояние git&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[git_branch]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ $symbol$branch(:$remote_branch) ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;fg:#1C3A5E bg:#FCF392&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[git_metrics]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_metrics&lt;/code&gt; &lt;strong&gt;выключен по умолчанию&lt;/strong&gt;, и его стоит включить — это то самое &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+1 -32&lt;/code&gt; в примере, добавленные и удалённые строки с последнего коммита. Разница между «я знаю, что есть изменения» и «я знаю, насколько они большие».&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_status&lt;/code&gt; включён по умолчанию и не требует настройки. Его сокращения стоит запомнить:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Символ&lt;/th&gt;
        &lt;th&gt;Значение&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;изменённые файлы&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;неотслеживаемые файлы&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;файлы в индексе&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;есть stash&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⇡&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;⇣&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;впереди / позади remote&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;конфликт слияния&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Значит &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[!?] +1 -32&lt;/code&gt; читается так: есть изменённые и неотслеживаемые файлы, добавлена одна строка, удалено тридцать две.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;section-5&quot;&gt;Как прижать часть промпта вправо&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[fill]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;symbol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;[cmd_duration]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;min_time&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2_000&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[ ⏲︎ $duration ]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;white&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Модуль &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill&lt;/code&gt; растягивается на всю оставшуюся ширину терминала. Всё, что стоит после него в format, уезжает к правому краю. Так версия Node и Docker-контекст оказываются выровнены по правому краю без ручных отступов.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd_duration&lt;/code&gt; с &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;min_time = 2000&lt;/code&gt; появляется только если команда выполнялась дольше двух секунд. Молчит, когда неважно, говорит, когда важно — правильное поведение почти для любого сегмента промпта.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;all---&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$all&lt;/code&gt; — всё остальное&lt;/h3&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$all&lt;/code&gt; в конце format — это подстановочный знак: он отрисовывает все модули, не упомянутые явно. Оттуда берутся &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;via  v24.4.0&lt;/code&gt; и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;via 🐳 colima&lt;/code&gt; — я никогда не настраивал ни модуль Node, ни модуль Docker. Starship нашёл &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; и активный Docker-контекст и сообщил об этом.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Так же с виртуальными окружениями Python, тулчейнами Rust, версиями Ruby, контекстами Kubernetes, профилями AWS. Самое высокое отношение полезной информации к объёму конфига во всём файле.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Если вылезает язык, который вам не нужен — выключите его отдельно:&lt;/p&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[ruby]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;disabled&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;section-6&quot;&gt;Вторая строка&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-toml&quot; data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;nn&quot;&gt;[custom.git_config_email]&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Показать email из текущей конфигурации git.&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git config user.email&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[$symbol(  $output)]($style)&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;git rev-parse --is-inside-work-tree &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&quot;&lt;/span&gt;
&lt;span class=&quot;py&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Это тот сегмент, который я бы оставил, если бы пришлось выбросить всё остальное.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Если вы работаете с личным и рабочим аккаунтами одновременно, рано или поздно вы закоммитите в один под личностью другого. И заметите через несколько недель, на код-ревью, в ветке, которую уже вмержили. Лечится через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git config user.email&lt;/code&gt; в каждом репозитории — но только если не забыть проверить, а проверить забывают все.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Поэтому проверяет промпт. Каждый раз. Отдельной строкой, приглушённым текстом, только внутри репозиториев.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-7&quot;&gt;Слой 4 — Обвязка вокруг&lt;/h2&gt;

  &lt;p&gt;Промпт — это то, что замечают. А вот чего мне действительно не хватало бы:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;atuin-----&quot;&gt;atuin — история как база данных&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;atuin init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
bindkey &lt;span class=&quot;s1&quot;&gt;&apos;^R&apos;&lt;/span&gt; atuin-search
bindkey &lt;span class=&quot;s1&quot;&gt;&apos;^[[A&apos;&lt;/span&gt; atuin-search   &lt;span class=&quot;c&quot;&gt;# перехватываем ещё и стрелку вверх&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Atuin заменяет &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zsh_history&lt;/code&gt; на базу SQLite и даёт полноэкранный нечёткий поиск по ней — с фильтром по директории, с кодами возврата и длительностью выполнения. Второй &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindkey&lt;/code&gt; — вкусовщина: он перехватывает ещё и &lt;strong&gt;стрелку вверх&lt;/strong&gt;, чтобы уже выработанный рефлекс открывал хороший поиск вместо плохого.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;zoxide--cd--&quot;&gt;zoxide — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;, который учится&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;zoxide init zsh&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Запоминает, в какие директории вы реально ходите, и ранжирует их по частоте и свежести. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z risk&lt;/code&gt; прыгает в нужный репозиторий откуда угодно. Через неделю перестаёшь набирать пути.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;fzf----&quot;&gt;fzf — нечёткий поиск везде&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;fzf &lt;span class=&quot;nt&quot;&gt;--zsh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Одна строка — и &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-T&lt;/code&gt; становится нечётким выбором файла, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt-C&lt;/code&gt; — нечётким &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;. Множество других инструментов использует fzf как бэкенд, так что его установка улучшает даже то, что вы ещё не поставили.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;eza--ls----git&quot;&gt;eza — &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt;, который знает про git&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;eza --icons -l -F --colour=always -a --git --header --time-style=iso&apos;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ee2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;eza --icons -l -TL 2 --total-size -F --colour=always&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--git&lt;/code&gt; помечает каждый файл его git-статусом — именно этот флаг оправдывает переход на eza. Второй алиас — дерево на два уровня с размерами директорий, самый быстрый способ ответить на вопрос «что здесь занимает место».&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;yazi-------&quot;&gt;yazi — файловый менеджер, который меняет директорию оболочки&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;function &lt;/span&gt;y&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;local &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tmp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mktemp&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;yazi-cwd.XXXXXX&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; cwd
	yazi &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cwd-file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;nv&quot;&gt;IFS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&apos;&lt;/span&gt; cwd &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;builtin cd&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$cwd&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$tmp&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Дочерний процесс не может изменить рабочую директорию родителя, поэтому yazi записывает свою финальную директорию во временный файл, а обёртка потом делает туда &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;. Побродили визуально через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt;, вышли — и оболочка уже там, куда вы смотрели.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;h3 id=&quot;section-8&quot;&gt;Ещё одна строка, которую стоит украсть&lt;/h3&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;precmd&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; print &lt;span class=&quot;nt&quot;&gt;-Pn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\e&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;]0;%~&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\a&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Ставит в заголовок вкладки терминала текущую директорию перед каждым промптом. Мелочь — и при этом разница между шестью различимыми вкладками и шестью вкладками с подписью «zsh».&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-9&quot;&gt;Сколько это стоит&lt;/h2&gt;

  &lt;p&gt;За красивыми промптами тянется репутация медленных, и этот не бесплатный. Starship сам скажет, сколько именно:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;starship timings&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Замер в реальном репозитории на моей машине:&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;custom.git_config_email             -  15ms
custom.directory_separator_git      -   8ms
custom.directory_separator_not_git  -   7ms
ruby                                -   5ms
git_metrics                         -   4ms
directory                           -   4ms
git_branch                          -  &amp;lt;1ms&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Три кастомных модуля забирают &lt;strong&gt;30 мс из примерно 45 мс общих&lt;/strong&gt; — две трети стоимости ради одного email-адреса и одной косметической стрелки. Каждый из них порождает процесс на каждой отрисовке промпта, причём оба модуля-разделителя выполняют свою проверку, хотя отрисоваться может только один.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Модули считаются параллельно, поэтому по времени выходит меньше суммы. 45 мс держатся ниже порога, за которым промпт начинает ощущаться вялым, и проверку git-личности я считаю оправданной. Но это реальный размен, и полезно понимать, за какие строки конфига вы платите. Хотите эстетику без цены — уберите модули-разделителей и примите жёсткую границу цветов: вернёте 15 мс за изменение, которого большинство не заметит.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;И ещё немного честности: в моём конфиге в строке format болтается забытый &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$symbol&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol&lt;/code&gt; — не модуль, поэтому Starship молча рисует вместо него ничего. Он живёт там год и не делает ровным счётом ничего. Проверьте свой конфиг через &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;starship timings&lt;/code&gt; — всё, чего нет в выводе, не работает.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-10&quot;&gt;С чего начать&lt;/h2&gt;

  &lt;p&gt;Если возьмёте из статьи одну вещь — берите Nerd Font и Starship с дефолтным конфигом. Пятнадцать минут и большая часть визуального эффекта.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Если две — добавьте atuin. Искомая история с учётом директории меняет способ работы с оболочкой сильнее, чем любой промпт.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Остальное — украшательство. Хорошее, отточенное за пару лет, и я бы восстановил его целиком на новой машине — но украшательство.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Одно предупреждение, прежде чем копировать чьи-либо дотфайлы, включая мои: сначала проверьте их на секреты. API-токены, экспортированные в &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt; — самый частый способ превратить приватный репозиторий в публичный инцидент. Держите их в менеджере секретов и читайте в рантайме.&lt;/p&gt;
  &lt;/blockquote&gt;

&lt;/div&gt;

&lt;script&gt;
(function () {
  var btns = document.querySelectorAll(&apos;.lang-btn&apos;);
  window.setLang = function (lang) {
    document.getElementById(&apos;lang-en&apos;).style.display = lang === &apos;en&apos; ? &apos;block&apos; : &apos;none&apos;;
    document.getElementById(&apos;lang-ru&apos;).style.display = lang === &apos;ru&apos; ? &apos;block&apos; : &apos;none&apos;;
    btns.forEach(function (b) {
      b.classList.toggle(&apos;active&apos;, b.textContent.toLowerCase() === lang);
    });
    localStorage.setItem(&apos;post-lang-terminal&apos;, lang);
  };
  var saved = localStorage.getItem(&apos;post-lang-terminal&apos;);
  if (saved &amp;&amp; saved !== &apos;en&apos;) setLang(saved);
})();
&lt;/script&gt;</content>
  </entry>
  <entry>
    <title type="html">Hokum</title>
    <id>https://lobanov-av.ru/logs/2026-08-10-hokum-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-08-10-hokum-movie-log.html"/>
    <published>2026-08-10T00:00:00+00:00</published>
    <updated>2026-08-10T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="👻 Old-School Chills"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-08-10-hokum-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;A classic haunted house story done really well — one old Irish hotel, a lot of &lt;strong&gt;folklore and atmosphere&lt;/strong&gt;, and scares that land exactly when they should. Adam Scott plays a horror writer who came to scatter his parents’ ashes, and it’s &lt;strong&gt;the best work he has done on screen&lt;/strong&gt;. McCarthy builds the whole film out of one location and still keeps it tense the whole time. &lt;strong&gt;Slow, quiet horror&lt;/strong&gt; that actually has a brain — not for people who want jump scares every five minutes.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Spider-Man: Brand New Day</title>
    <id>https://lobanov-av.ru/logs/2026-08-09-spider-man-brand-new-day-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-08-09-spider-man-brand-new-day-movie-log.html"/>
    <published>2026-08-09T00:00:00+00:00</published>
    <updated>2026-08-09T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🕷️ Perfect Superhero Fun"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-08-09-spider-man-brand-new-day-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;The director keeps things simple and just lets Spider-Man &lt;strong&gt;move&lt;/strong&gt; — the fights and the swinging are the best action the MCU has done in years. Peter is &lt;strong&gt;finally a grown-up&lt;/strong&gt;, and the whole story stays in &lt;strong&gt;New York&lt;/strong&gt;, which fits him much better. Holland is really good here, Bernthal steals every scene, and &lt;strong&gt;Sadie Sink is just as strong&lt;/strong&gt;. The one thing I didn’t like: &lt;strong&gt;MJ and Ned get maybe ten minutes&lt;/strong&gt; in the whole film, so their part feels pointless. Not a masterpiece, but a &lt;strong&gt;great sequel&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">The Odyssey</title>
    <id>https://lobanov-av.ru/logs/2026-08-03-odyssey-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-08-03-odyssey-movie-log.html"/>
    <published>2026-08-03T00:00:00+00:00</published>
    <updated>2026-08-03T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🎞️ Nolan&apos;s Epic Journey"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-08-03-odyssey-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Nolan takes the oldest story ever told and turns it into something &lt;strong&gt;massive and hypnotic&lt;/strong&gt;. We went to IMAX for the first time in ages, and that made it hit twice as hard — the scale, the sound, the weight of every frame. Ludwig Göransson’s score has been &lt;strong&gt;on repeat for a week straight&lt;/strong&gt; since. &lt;strong&gt;Best film of the year&lt;/strong&gt;, no contest.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Write the Spec First</title>
    <id>https://lobanov-av.ru/2026/05/13/spec-driven-development.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/2026/05/13/spec-driven-development.html"/>
    <published>2026-05-13T00:00:00+00:00</published>
    <updated>2026-05-13T00:00:00+00:00</updated>
    <category term="Thoughts"/>
    <summary type="html">Vibe coding worked for prototypes. For real projects, AI needs a blueprint — not a wish.</summary><content type="html" xml:base="https://lobanov-av.ru/2026/05/13/spec-driven-development.html">&lt;style&gt;
.lang-toggle {
  position: absolute;
  top: 15px;
  right: 18px;
  display: flex;
  gap: 6px;
}
.lang-btn {
  font-family: var(--code-font);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 12px;
  border-radius: 8px;
  border: 1px solid var(--border-color);
  background-color: var(--background-color-light);
  color: var(--primary-color);
  cursor: pointer;
  margin: 0;
  transition: background-color 0.2s ease;
}
.lang-btn.active {
  background-color: var(--secondary-color);
  color: var(--background-color);
  border-color: var(--secondary-color);
}
&lt;/style&gt;

&lt;div class=&quot;lang-toggle&quot;&gt;
  &lt;button class=&quot;lang-btn active&quot; onclick=&quot;setLang(&apos;en&apos;)&quot;&gt;EN&lt;/button&gt;
  &lt;button class=&quot;lang-btn&quot; onclick=&quot;setLang(&apos;ru&apos;)&quot;&gt;RU&lt;/button&gt;
&lt;/div&gt;

&lt;div id=&quot;lang-en&quot;&gt;

  &lt;hr /&gt;

  &lt;blockquote&gt;
    &lt;p&gt;I typed: &lt;em&gt;“Add biometric authentication with token refresh”&lt;/em&gt;. The AI built it. It ran. Unit tests passed. Then code review happened — and the whole thing had to be thrown out. No one had talked about the existing Keychain wrapper, the token rotation strategy already in place, or that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiometricService&lt;/code&gt; was already handling the LAContext lifecycle.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The code was correct. The spec was missing.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;the-pattern-everyone-hits&quot;&gt;The Pattern Everyone Hits&lt;/h2&gt;

  &lt;p&gt;AI coding agents are fast. Dangerously fast. You describe a feature in a sentence, and within seconds you have a full implementation — view models, services, tests.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The problem: &lt;strong&gt;the AI implements what it guesses you want, not what you actually want&lt;/strong&gt;. And the gap between those two things is where all the rewrites live.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;It has a name now: &lt;strong&gt;context collapse&lt;/strong&gt;. The moment the agent forgets what it was supposed to be building — because the context window filled up, or because the original intent was never precise enough to survive the session.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;spec-driven-development&quot;&gt;Spec-Driven Development&lt;/h2&gt;

  &lt;p&gt;The fix isn’t a better prompt. It’s a better spec.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;Spec-Driven Development (SDD)&lt;/strong&gt; flips the workflow: instead of jumping straight to &lt;em&gt;“implement this”&lt;/em&gt;, you write a structured spec first — what we’re building, why, and the constraints. Then the AI implements &lt;em&gt;against that spec&lt;/em&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The workflow has four phases:&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Specify&lt;/strong&gt; — write the spec in markdown, stored in the repo&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Plan&lt;/strong&gt; — AI breaks the spec into tasks&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Review&lt;/strong&gt; — tasks are validated by a human&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Implement&lt;/strong&gt; — AI writes code against the approved task list&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;You own the spec. The agent owns nothing — it just implements.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;what-a-spec-looks-like&quot;&gt;What a Spec Looks Like&lt;/h2&gt;

  &lt;p&gt;A spec isn’t a novel. It’s a short markdown file — what we’re building, the constraints, and the decisions that aren’t obvious from the code.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;gu&quot;&gt;## Feature: Biometric Authentication&lt;/span&gt;

&lt;span class=&quot;gu&quot;&gt;### Goal&lt;/span&gt;
Add Face ID / Touch ID login using the existing &lt;span class=&quot;sb&quot;&gt;`BiometricService`&lt;/span&gt;.

&lt;span class=&quot;gu&quot;&gt;### Constraints&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Must use existing &lt;span class=&quot;sb&quot;&gt;`KeychainWrapper`&lt;/span&gt; for token storage
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Token refresh handled by &lt;span class=&quot;sb&quot;&gt;`AuthInterceptor`&lt;/span&gt; — do not duplicate
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; LAContext lifecycle is managed by &lt;span class=&quot;sb&quot;&gt;`BiometricService`&lt;/span&gt; — do not create new instances
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; No new dependencies

&lt;span class=&quot;gu&quot;&gt;### Out of scope&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Passcode fallback UI (separate ticket)
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Android biometrics&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;That’s it. Five lines of constraints. But now the AI has a contract, not a wish.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;the-shift&quot;&gt;The Shift&lt;/h2&gt;

  &lt;p&gt;Vibe coding felt like magic when it worked. But as the codebase grows, prompts get longer, the agent starts contradicting itself, and you spend more time debugging AI output than writing code.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Spec-driven development doesn’t remove AI from the loop. It gives AI something solid to work against. Tools like &lt;a href=&quot;https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/&quot;&gt;GitHub Spec Kit&lt;/a&gt; are already making this a first-class workflow.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;The new developer role isn’t typing code. It’s &lt;strong&gt;writing specs and reviewing implementations&lt;/strong&gt;. That’s the job now.&lt;/p&gt;

&lt;/div&gt;

&lt;div id=&quot;lang-ru&quot; style=&quot;display:none&quot;&gt;

  &lt;hr /&gt;

  &lt;blockquote&gt;
    &lt;p&gt;Я написал: &lt;em&gt;«Добавь биометрическую аутентификацию с обновлением токена»&lt;/em&gt;. AI построил. Запустилось. Юнит-тесты прошли. Потом был код-ревью — и всё выбросили. Никто не говорил о существующем &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;KeychainWrapper&lt;/code&gt;, о стратегии ротации токенов, которая уже была, и о том, что &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BiometricService&lt;/code&gt; уже управляет жизненным циклом &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LAContext&lt;/code&gt;.&lt;/p&gt;
  &lt;/blockquote&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Код был правильным. Спека не было.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section&quot;&gt;Паттерн, на который все натыкаются&lt;/h2&gt;

  &lt;p&gt;AI-агенты быстрые. Опасно быстрые. Описываешь фичу одним предложением — и через секунды у тебя полная реализация: вью-модели, сервисы, тесты.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Проблема: &lt;strong&gt;AI реализует то, что, по его мнению, ты хочешь — а не то, что ты на самом деле хочешь&lt;/strong&gt;. И в этом разрыве живут все переписывания.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;У этого есть имя: &lt;strong&gt;context collapse&lt;/strong&gt;. Момент, когда агент забывает, что вообще строил — потому что контекстное окно переполнилось, или потому что изначальное намерение было недостаточно точным, чтобы пережить сессию.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;spec-driven-development-1&quot;&gt;Spec-Driven Development&lt;/h2&gt;

  &lt;p&gt;Решение — не лучший промпт. Это лучший спек.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;&lt;strong&gt;Spec-Driven Development (SDD)&lt;/strong&gt; переворачивает воркфлоу: вместо того, чтобы сразу говорить &lt;em&gt;«реализуй это»&lt;/em&gt;, сначала пишешь структурированный спек — что строим, почему, ограничения. Потом AI реализует &lt;em&gt;по этому спеку&lt;/em&gt;.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Воркфлоу из четырёх этапов:&lt;/p&gt;

  &lt;ol&gt;
    &lt;li&gt;&lt;strong&gt;Specify&lt;/strong&gt; — пишешь спек в markdown, он хранится в репо&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Plan&lt;/strong&gt; — AI разбивает спек на задачи&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Review&lt;/strong&gt; — задачи проверяет человек&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Implement&lt;/strong&gt; — AI пишет код по утверждённому списку задач&lt;/li&gt;
  &lt;/ol&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Спек — твоя зона. Агент ничем не владеет — он просто реализует.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-1&quot;&gt;Как выглядит спек&lt;/h2&gt;

  &lt;p&gt;Спек — не роман. Это короткий markdown-файл — что строим, ограничения и решения, которые не очевидны из кода.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-markdown&quot; data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;gu&quot;&gt;## Feature: Biometric Authentication&lt;/span&gt;

&lt;span class=&quot;gu&quot;&gt;### Goal&lt;/span&gt;
Add Face ID / Touch ID login using the existing &lt;span class=&quot;sb&quot;&gt;`BiometricService`&lt;/span&gt;.

&lt;span class=&quot;gu&quot;&gt;### Constraints&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Must use existing &lt;span class=&quot;sb&quot;&gt;`KeychainWrapper`&lt;/span&gt; for token storage
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Token refresh handled by &lt;span class=&quot;sb&quot;&gt;`AuthInterceptor`&lt;/span&gt; — do not duplicate
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; LAContext lifecycle is managed by &lt;span class=&quot;sb&quot;&gt;`BiometricService`&lt;/span&gt; — do not create new instances
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; No new dependencies

&lt;span class=&quot;gu&quot;&gt;### Out of scope&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Passcode fallback UI (separate ticket)
&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt; Android biometrics&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Всё. Пять строк ограничений. Но теперь у AI есть контракт, а не пожелание.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;hr /&gt;

  &lt;h2 id=&quot;section-2&quot;&gt;Перемены&lt;/h2&gt;

  &lt;p&gt;Vibe coding ощущался как магия, когда работал. Но по мере роста кодовой базы промпты становятся длиннее, агент начинает противоречить сам себе, и ты тратишь больше времени на отладку AI-вывода, чем на написание кода.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Spec-driven development не убирает AI из процесса. Он даёт AI что-то надёжное, против чего работать. Инструменты вроде &lt;a href=&quot;https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-new-open-source-toolkit/&quot;&gt;GitHub Spec Kit&lt;/a&gt; уже делают это первоклассным воркфлоу.&lt;/p&gt;

  &lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

  &lt;p&gt;Новая роль разработчика — не набирать код. Это &lt;strong&gt;писать спеки и проверять реализации&lt;/strong&gt;. Теперь это и есть работа.&lt;/p&gt;

&lt;/div&gt;

&lt;script&gt;
(function () {
  var btns = document.querySelectorAll(&apos;.lang-btn&apos;);
  window.setLang = function (lang) {
    document.getElementById(&apos;lang-en&apos;).style.display = lang === &apos;en&apos; ? &apos;block&apos; : &apos;none&apos;;
    document.getElementById(&apos;lang-ru&apos;).style.display = lang === &apos;ru&apos; ? &apos;block&apos; : &apos;none&apos;;
    btns.forEach(function (b) {
      b.classList.toggle(&apos;active&apos;, b.textContent.toLowerCase() === lang);
    });
    localStorage.setItem(&apos;post-lang-spec&apos;, lang);
  };
  var saved = localStorage.getItem(&apos;post-lang-spec&apos;);
  if (saved &amp;&amp; saved !== &apos;en&apos;) setLang(saved);
})();
&lt;/script&gt;</content>
  </entry>
  <entry>
    <title type="html">Folded Mood</title>
    <id>https://lobanov-av.ru/logs/2026-04-27-folded-mood-music-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-04-27-folded-mood-music-log.html"/>
    <published>2026-04-27T00:00:00+00:00</published>
    <updated>2026-04-27T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-04-27-folded-mood-music-log.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/soundcloud%253Atracks%253A2309733584&amp;amp;color=%23987c64&amp;amp;auto_play=false&amp;amp;hide_related=true&amp;amp;show_comments=false&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=false&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/rob0tlegs&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/rob0tlegs/folded-mood&quot; title=&quot;Folded Mood&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Folded Mood&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Project Hail Mary</title>
    <id>https://lobanov-av.ru/logs/2026-03-22-project-hail-mary-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-03-22-project-hail-mary-movie-log.html"/>
    <published>2026-03-22T00:00:00+00:00</published>
    <updated>2026-03-22T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🚀 Sci-Fi Triumph"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-03-22-project-hail-mary-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Ryan Gosling carries this film with genuine charm and emotion. The story is &lt;strong&gt;clever, warm, and surprisingly funny&lt;/strong&gt; — science fiction at its most human. One of those rare movies where you don’t want it to end.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Resident Evil Requiem</title>
    <id>https://lobanov-av.ru/logs/2026-03-15-resident-evil-requiem-game-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-03-15-resident-evil-requiem-game-log.html"/>
    <published>2026-03-15T00:00:00+00:00</published>
    <updated>2026-03-15T00:00:00+00:00</updated>
    <category term="game"/>
    <category term="🧟 RE Back to Form"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-03-15-resident-evil-requiem-game-log.html">&lt;blockquote&gt;
  &lt;p&gt;A fantastic entry in the series. Playing as &lt;strong&gt;Grace Ashcroft&lt;/strong&gt; is an absolute highlight — her storyline is fresh, tense, and well-crafted throughout. Leon’s abandoned city section was the one weak spot: pointless backtracking that felt directionless and out of place. But that’s a minor complaint — the game overall is one of the &lt;strong&gt;best Resident Evil titles in years&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Frankenstein</title>
    <id>https://lobanov-av.ru/logs/2026-02-01-frankenstein-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-02-01-frankenstein-movie-log.html"/>
    <published>2026-02-01T00:00:00+00:00</published>
    <updated>2026-02-01T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="⚡ Del Toro&apos;s Darkness"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-02-01-frankenstein-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Del Toro’s most &lt;strong&gt;visually stunning work&lt;/strong&gt; yet. Oscar Isaac and Jacob Elordi bring real emotional weight to the iconic story. Dark, gorgeous, and deeply felt — exactly the kind of film only he could make.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">One Battle After Another</title>
    <id>https://lobanov-av.ru/logs/2026-01-21-one-battle-after-another-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-01-21-one-battle-after-another-movie-log.html"/>
    <published>2026-01-21T00:00:00+00:00</published>
    <updated>2026-01-21T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="⚡ PTA&apos;s War Epic"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-01-21-one-battle-after-another-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Paul Thomas Anderson at his most &lt;strong&gt;chaotic and alive&lt;/strong&gt;. DiCaprio is magnetic, but it’s Del Toro who absolutely owns the screen every time he appears. An instant classic — don’t sleep on it.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Avatar: Fire and Ash</title>
    <id>https://lobanov-av.ru/logs/2026-01-05-avatar-fire-and-ash-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2026-01-05-avatar-fire-and-ash-movie-log.html"/>
    <published>2026-01-05T00:00:00+00:00</published>
    <updated>2026-01-05T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🌋 Gorgeous but Hollow"/><content type="html" xml:base="https://lobanov-av.ru/logs/2026-01-05-avatar-fire-and-ash-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Cameron delivers exactly what you came for — &lt;strong&gt;jaw-dropping visuals and world-building&lt;/strong&gt; that no one else can match. The story takes a back seat, but when it looks this good, you forgive it instantly.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">The Phoenician Scheme</title>
    <id>https://lobanov-av.ru/logs/2025-11-07-phoenician-scheme-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-11-07-phoenician-scheme-movie-log.html"/>
    <published>2025-11-07T00:00:00+00:00</published>
    <updated>2025-11-07T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🕊️ Wes Anderson Perfection"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-11-07-phoenician-scheme-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;The Phoenician Scheme&lt;/strong&gt; is a dazzling feast for the eyes — Wes Anderson’s signature symmetry, color, and wit come together in a film that’s equal parts absurd, elegant, and irresistibly stylish. Every frame feels like a painting in motion, making it impossible to look away even for a second.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Barbarian</title>
    <id>https://lobanov-av.ru/logs/2025-11-06-barbarian-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-11-06-barbarian-movie-log.html"/>
    <published>2025-11-06T00:00:00+00:00</published>
    <updated>2025-11-06T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🚪 Do Not Open the Door"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-11-06-barbarian-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Another knockout from Cregger. The film keeps you completely off-balance — every time you think you know where it’s going, it pulls the rug out. &lt;strong&gt;Smart, creepy, and endlessly surprising.&lt;/strong&gt; A must-watch for any horror fan.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Weapons</title>
    <id>https://lobanov-av.ru/logs/2025-11-05-weapons-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-11-05-weapons-movie-log.html"/>
    <published>2025-11-05T00:00:00+00:00</published>
    <updated>2025-11-05T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="👁️ American Horror Mosaic"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-11-05-weapons-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;Zach Cregger delivers something &lt;strong&gt;genuinely unsettling and original&lt;/strong&gt;. Multiple storylines weave together in ways you don’t see coming — tense, disturbing, and brilliantly constructed. One of the &lt;strong&gt;best horror films in years&lt;/strong&gt;, full stop.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Ghost of Yotei</title>
    <id>https://lobanov-av.ru/logs/2025-09-26-ghost-of-yotai-game-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-09-26-ghost-of-yotai-game-log.html"/>
    <published>2025-10-26T00:00:00+00:00</published>
    <updated>2025-10-26T00:00:00+00:00</updated>
    <category term="game"/>
    <category term="🦊 Ghost of Tsushima 2.0"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-09-26-ghost-of-yotai-game-log.html">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Ghost of Yotei&lt;/strong&gt; stuns with its breathtaking visuals — every frame feels alive, turning the game into a true work of art. The combat system is exceptional: fluid, intense, and as elegant as a master samurai’s strike.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Mickey 17</title>
    <id>https://lobanov-av.ru/logs/2025-11-03-november-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-11-03-november-movie-log.html"/>
    <published>2025-10-23T00:00:00+00:00</published>
    <updated>2025-10-23T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🤖 Bong Joon-ho Returns"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-11-03-november-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Mickey 17&lt;/strong&gt; feels predictable at times, but Robert Pattinson’s performance gives it real weight and charisma. A few standout moments shine through the familiarity, leaving a genuinely strong impression despite the film’s uneven pacing.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Code 3</title>
    <id>https://lobanov-av.ru/logs/2025-10-18-code-3-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-10-18-code-3-movie-log.html"/>
    <published>2025-10-18T00:00:00+00:00</published>
    <updated>2025-10-18T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="😅 Absurdist Comedy"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-10-18-code-3-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;If you only knew Rainn Wilson from &lt;em&gt;The Office&lt;/em&gt;, prepare to be surprised — he’s &lt;strong&gt;genuinely great&lt;/strong&gt; here, carrying the whole film. Funny, raw, and unexpectedly moving.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Song is for a calm mood</title>
    <id>https://lobanov-av.ru/logs/2025-09-11-song-for-calm-mood.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-09-11-song-for-calm-mood.html"/>
    <published>2025-09-11T00:00:00+00:00</published>
    <updated>2025-09-11T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-09-11-song-for-calm-mood.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/2169062379&amp;amp;color=%23a4a191&amp;amp;auto_play=false&amp;amp;hide_related=false&amp;amp;show_comments=true&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=true&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/rob0tlegs&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/rob0tlegs/song-is-for-a-calm-mood&quot; title=&quot;Song is for a calm mood&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Song is for a calm mood&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Caught Stealing</title>
    <id>https://lobanov-av.ru/logs/2025-09-05-caught-stealing-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-09-05-caught-stealing-movie-log.html"/>
    <published>2025-09-05T00:00:00+00:00</published>
    <updated>2025-09-05T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="🏃 Wrong Place, Wrong Time"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-09-05-caught-stealing-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;The film doesn’t always land, but the &lt;strong&gt;duos are the real show&lt;/strong&gt; — Kolokolnikov and Kukushkin are magnetic together, and Schreiber &amp;amp; D’Onofrio as the Hasidic mob brothers Lipa and Shmully steal every scene they’re in. Watch it for them.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Senua&apos;s Saga: Hellblade II</title>
    <id>https://lobanov-av.ru/logs/2025-08-30-senua2-game-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-08-30-senua2-game-log.html"/>
    <published>2025-08-19T00:00:00+00:00</published>
    <updated>2025-08-19T00:00:00+00:00</updated>
    <category term="game"/>
    <category term="Photorealistic"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-08-30-senua2-game-log.html">&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Hellblade II&lt;/strong&gt; impresses with its visual detail and sound design, creating a powerful atmosphere and deep emotional impact. Despite criticism for repetitive combat and limited player agency, the game stands out for its strong narrative and cinematic quality, honestly and vividly portraying the inner world of the main character.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Death Stranding 2</title>
    <id>https://lobanov-av.ru/logs/2025-08-19-ds2-game-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-08-19-ds2-game-log.html"/>
    <published>2025-08-19T00:00:00+00:00</published>
    <updated>2025-08-19T00:00:00+00:00</updated>
    <category term="game"/>
    <category term="📦 Kojima Does It Again"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-08-19-ds2-game-log.html">&lt;blockquote&gt;
  &lt;p&gt;Second &lt;strong&gt;Death Stranding&lt;/strong&gt; is an atmospheric and unusual game that really impressed me with its visuals — the graphics are excellent. Even if you don’t plan to play, you should definitely watch how &lt;a href=&quot;https://www.youtube.com/watch?v=LXctji7Y3I4&quot;&gt;Tommorow fights the mech-ghosts&lt;/a&gt;, how one of the &lt;a href=&quot;https://www.youtube.com/watch?v=O91YcZWcUVY&quot;&gt;characters dances in the oil&lt;/a&gt;, and how the main villain and the main hero have a &lt;a href=&quot;https://www.youtube.com/watch?v=9SSe62ZOQNI&quot;&gt;guitar duel&lt;/a&gt; — it’s a spectacle worth seeing.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Working with LLMs</title>
    <id>https://lobanov-av.ru/2025/07/27/thoughts-llm.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/2025/07/27/thoughts-llm.html"/>
    <published>2025-07-27T00:00:00+00:00</published>
    <updated>2025-07-27T00:00:00+00:00</updated>
    <category term="Thoughts"/>
    <summary type="html">LLMs are like a stubborn donkey, a tricky genie, and a slot machine all in one — you need to know how to work with them.</summary><content type="html" xml:base="https://lobanov-av.ru/2025/07/27/thoughts-llm.html">&lt;p&gt;&lt;strong&gt;Large language models (LLMs)&lt;/strong&gt; are like a stubborn &lt;strong&gt;donkey&lt;/strong&gt;: always eager to help, but never admitting they don’t know something. Or like a &lt;strong&gt;genie&lt;/strong&gt;: granting your wishes literally, with results that might surprise you. And sometimes they’re just a &lt;strong&gt;slot machine&lt;/strong&gt; — spin it, and you never know if you’ll hit the jackpot or get nothing. So &lt;strong&gt;don’t expect miracles&lt;/strong&gt;: you need to know how to work with LLMs, otherwise you might end up with neither your wish nor your winnings!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">It&apos;s your fault</title>
    <id>https://lobanov-av.ru/logs/2025-06-04-its-your-fault.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-06-04-its-your-fault.html"/>
    <published>2025-06-04T00:00:00+00:00</published>
    <updated>2025-06-04T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-06-04-its-your-fault.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/2107281036&amp;amp;color=%235c543c&amp;amp;auto_play=false&amp;amp;hide_related=true&amp;amp;show_comments=false&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=false&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1/glitch-is-yours&quot; title=&quot;It&amp;#x27;s your fault&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;It&amp;#x27;s your fault&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Diverse Louse</title>
    <id>https://lobanov-av.ru/logs/2025-05-21-diverse-louse.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-05-21-diverse-louse.html"/>
    <published>2025-05-21T00:00:00+00:00</published>
    <updated>2025-05-21T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-05-21-diverse-louse.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/2099778030&amp;amp;color=%2374806c&amp;amp;auto_play=false&amp;amp;hide_related=true&amp;amp;show_comments=false&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=false&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1/diverse-louse&quot; title=&quot;Diverse Louse&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Diverse Louse&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Clair Obscur: Expedition 33</title>
    <id>https://lobanov-av.ru/logs/2025-05-15-obscure-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-05-15-obscure-log.html"/>
    <published>2025-05-15T00:00:00+00:00</published>
    <updated>2025-05-15T00:00:00+00:00</updated>
    <category term="game"/>
    <category term="🎨 Most Beautiful RPG of 2025"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-05-15-obscure-log.html">&lt;blockquote&gt;
  &lt;p&gt;A captivating story with unexpected twists, stunning visual style, and dynamic turn-based combat in the spirit of Final Fantasy. The game creates a unique atmosphere where each battle is a true test of tactical thinking. If you enjoyed this game, you might want to try more classic turn-based RPGs like &lt;a href=&quot;https://opencritic.com/game/4905/battle-chasers-nightwar&quot;&gt;Battle Chasers: Nightwar&lt;/a&gt; or &lt;a href=&quot;https://opencritic.com/game/15003/sea-of-stars&quot;&gt;Sea of Stars&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Daily Stand-Up? Handled.</title>
    <id>https://lobanov-av.ru/2025/05/15/daily-dev-report-git-chatgpt.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/2025/05/15/daily-dev-report-git-chatgpt.html"/>
    <published>2025-05-15T00:00:00+00:00</published>
    <updated>2025-05-15T00:00:00+00:00</updated>
    <category term="Automation"/>
    <summary type="html">How I automated my daily developer report using a simple Git script and a prompt for ChatGPT — never blank out at a stand-up again.</summary><content type="html" xml:base="https://lobanov-av.ru/2025/05/15/daily-dev-report-git-chatgpt.html">&lt;hr /&gt;

&lt;blockquote&gt;
  &lt;p&gt;As a developer, I often found myself dreading one simple question in daily stand-ups: 
&lt;strong&gt;”- What did you work on yesterday?”&lt;/strong&gt;. 
I’d mentally rewind the day, try to recall commits, branches, context switches — and inevitably forget something.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

&lt;p&gt;So &lt;strong&gt;I built a &lt;a href=&quot;https://github.com/alobanov/daily-report&quot;&gt;script&lt;/a&gt;&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/strong&gt; that solved the problem once and for all.&lt;/p&gt;

&lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;-what-it-does&quot;&gt;📋 What It Does?&lt;/h2&gt;

&lt;p&gt;Every morning, I run a script that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Gathers all my &lt;strong&gt;Git&lt;/strong&gt; commits from the previous day.&lt;/li&gt;
  &lt;li&gt;Groups them by branch.&lt;/li&gt;
  &lt;li&gt;Displays them in a clean, readable format.&lt;/li&gt;
  &lt;li&gt;Appends a custom prompt that I paste into &lt;strong&gt;ChatGPT&lt;/strong&gt; — and boom — it generates a clear, concise status update for my stand-up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s what the Git output looks like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;❯ python3 git_log.py &lt;span class=&quot;nt&quot;&gt;--date&lt;/span&gt; 2025-05-15

📦 Commits by &lt;span class=&quot;s1&quot;&gt;&apos;Aleksey Lobanov&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;2025-05-15:

🔀 Branch: develop
• a2f9b3d1e 2025-05-15 MOB-762-settings-theme-switcher-finalization
• c8412eb74 2025-05-15 MOB-781-user-session-cleanup-on-logout

🔀 Branch: MOB-762-settings-theme-switcher-finalization
• 14cbe81e3 2025-05-15 feat&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;settings&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: MOB-762 implement dynamic theme switching with persistence across sessions
• f3d5e66ba 2025-05-15 refactor&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;ui&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: MOB-762 extract common theme logic into ThemeController
• 7e9123a84 2025-05-15 fix&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;auth&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;: MOB-762 ensure proper cleanup of tokens and session state on manual &lt;span class=&quot;nb&quot;&gt;logout&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then I append this prompt below:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;🔧 Generate a daily summary &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;the commits above &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;this format:

Yesterday:
- &amp;lt;summary of task 1&amp;gt;
- &amp;lt;summary of task 2&amp;gt;

📌 Rules:
• Group commits by branch. Each branch &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 1 task.
• Describe what was &lt;span class=&quot;k&quot;&gt;done &lt;/span&gt;abstractly, no low-level detail.
• If any MOB- tasks appear &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;develop, they are considered completed.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;ChatGPT does the rest. And now, I never draw a blank in a daily sync again. Here is the result:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Yesterday:
- Completed task MOB-762 — finalized implementation of theme switching &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;app settings with improved logic reuse and persistent behavior across sessions.
- Completed task MOB-781 — ensured proper cleanup of user session data during &lt;span class=&quot;nb&quot;&gt;logout &lt;/span&gt;to improve stability and security.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

&lt;h3 id=&quot;-why-this-works&quot;&gt;🧠 Why This Works&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;No more manual memory scanning.&lt;/li&gt;
  &lt;li&gt;Instant context when switching tasks or reviewing progress.&lt;/li&gt;
  &lt;li&gt;Easy way to track completed vs. in-progress work.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;️-implementation--usage&quot;&gt;🛠️ Implementation &amp;amp; Usage&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/alobanov/daily-report&quot;&gt;The script&lt;/a&gt;&lt;sup id=&quot;fnref:1:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; is now available as a standalone tool with additional features:&lt;/p&gt;

&lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

&lt;h4 id=&quot;quick-start&quot;&gt;Quick Start&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Setup&lt;/span&gt;
❯ python3.12 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; venv venv &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; requirements.txt
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;OPENAI_API_KEY=sk-...&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; .env

&lt;span class=&quot;c&quot;&gt;# Run&lt;/span&gt;
❯ python git_daily_report.py &lt;span class=&quot;nt&quot;&gt;--date&lt;/span&gt; YYYY-MM-DD&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;key-features&quot;&gt;Key Features&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Automatic ChatGPT API integration&lt;/li&gt;
  &lt;li&gt;Custom repository and author filtering&lt;/li&gt;
  &lt;li&gt;Flexible output formats&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;usage-examples&quot;&gt;Usage Examples&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;c&quot;&gt;# Basic usage&lt;/span&gt;
❯ python git_daily_report.py

&lt;span class=&quot;c&quot;&gt;# With ChatGPT API&lt;/span&gt;
❯ python git_daily_report.py &lt;span class=&quot;nt&quot;&gt;--use-gpt&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Specific repository&lt;/span&gt;
❯ python git_daily_report.py &lt;span class=&quot;nt&quot;&gt;--repo&lt;/span&gt; /path/to/repo

&lt;span class=&quot;c&quot;&gt;# Custom author&lt;/span&gt;
❯ python git_daily_report.py &lt;span class=&quot;nt&quot;&gt;--email&lt;/span&gt; user@example.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s a simple fix, but it’s changed the way I show up to stand-ups.
If you’re a dev who forgets what you did yesterday — this little combo of &lt;strong&gt;Git + Python + ChatGPT&lt;/strong&gt; might save your mornings.&lt;/p&gt;

&lt;div class=&quot;spacer&quot;&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;-feedback&quot;&gt;💬 Feedback&lt;/h3&gt;
&lt;p&gt;If you have suggestions for improving the script or have found a bug, please create an issue on GitHub&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; or join our community discussions&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/alobanov/daily-report&quot;&gt;GitHub Repository&lt;/a&gt; - Full source code and documentation &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:1:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/alobanov/daily-report/issues&quot;&gt;GitHub Issues&lt;/a&gt; - Report bugs or suggest improvements &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/alobanov/daily-report/discussions&quot;&gt;GitHub Discussions&lt;/a&gt; - Join the community discussion &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Glowing Chin</title>
    <id>https://lobanov-av.ru/logs/2025-05-13-glowing-chin.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-05-13-glowing-chin.html"/>
    <published>2025-05-13T00:00:00+00:00</published>
    <updated>2025-05-13T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-05-13-glowing-chin.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/2092854651&amp;amp;color=%23682418&amp;amp;auto_play=false&amp;amp;hide_related=true&amp;amp;show_comments=false&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=false&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1/glowing-chin&quot; title=&quot;Glowing Chin&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Glowing Chin&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">Body Mass Index (BMI)</title>
    <id>https://lobanov-av.ru/logs/2025-05-03-imb.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-05-03-imb.html"/>
    <published>2025-05-03T00:00:00+00:00</published>
    <updated>2025-05-03T00:00:00+00:00</updated>
    <category term="music"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-05-03-imb.html">&lt;iframe width=&quot;100%&quot; height=&quot;166&quot; scrolling=&quot;no&quot; frameborder=&quot;no&quot; allow=&quot;autoplay&quot; src=&quot;https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/2089125279&amp;amp;color=%23743e66&amp;amp;auto_play=false&amp;amp;hide_related=false&amp;amp;show_comments=true&amp;amp;show_user=true&amp;amp;show_reposts=false&amp;amp;show_teaser=true&quot;&gt;&lt;/iframe&gt;
&lt;div style=&quot;font-size: 10px; color: #cccccc;line-break: anywhere;word-break: normal;overflow: hidden;white-space: nowrap;text-overflow: ellipsis; font-family: Interstate,Lucida Grande,Lucida Sans Unicode,Lucida Sans,Garuda,Verdana,Tahoma,sans-serif;font-weight: 100;&quot;&gt;&lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1&quot; title=&quot;Robotlegs&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Robotlegs&lt;/a&gt; · &lt;a href=&quot;https://soundcloud.com/aleksey-lobanov-1/bmi&quot; title=&quot;Body Mass Index (BMI)&quot; target=&quot;_blank&quot; style=&quot;color: #cccccc; text-decoration: none;&quot;&gt;Body Mass Index (BMI)&lt;/a&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <title type="html">One Punch Man</title>
    <id>https://lobanov-av.ru/logs/2025-04-11-onepunchman-movie-log.html</id>
    <link rel="alternate" type="text/html" href="https://lobanov-av.ru/logs/2025-04-11-onepunchman-movie-log.html"/>
    <published>2025-04-11T00:00:00+00:00</published>
    <updated>2025-04-11T00:00:00+00:00</updated>
    <category term="movie"/>
    <category term="👊 Anime to Screen"/><content type="html" xml:base="https://lobanov-av.ru/logs/2025-04-11-onepunchman-movie-log.html">&lt;blockquote&gt;
  &lt;p&gt;It’s a animation series where the main character literally &lt;strong&gt;defeats everyone&lt;/strong&gt; with a single punch, without any effort.&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
</feed>
