<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Quoc.app</title>
    <subtitle>Independent maker building small, focused software for real problems.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://quoc.app/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://quoc.app"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-12T00:00:00+00:00</updated>
    <id>https://quoc.app/atom.xml</id>
    <entry xml:lang="en">
        <title>Write for myself</title>
        <published>2026-10-12T00:00:00+00:00</published>
        <updated>2026-10-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/20260916-185413-13f688/"/>
        <id>https://quoc.app/write/20260916-185413-13f688/</id>
        
        <content type="html" xml:base="https://quoc.app/write/20260916-185413-13f688/">&lt;h2 id=&quot;2026-10&quot;&gt;2026 10&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;x&lt;&#x2F;li&gt;
&lt;li&gt;cho hết đi, ta đâu có sống được lâu đâu&lt;&#x2F;li&gt;
&lt;li&gt;đổi hướng đi, không tệ khi nhìn lại, đó là điều đúng&lt;&#x2F;li&gt;
&lt;li&gt;thôi được rồi, yêu em thì nhìn em hạnh phúc là được rồi. Chẳng lẽ ta lại đòi sở hữu mới gọi là yêu? đéo gì vậy&lt;&#x2F;li&gt;
&lt;li&gt;và sau này mày nhận ra, thà mày dám thử, thay vì câm lặng. Và đấm vào mặt mày nhưng thực sự nó giúp mày tốt hơn về sau. Chỉ là giờ mày cảm thấy đau&lt;&#x2F;li&gt;
&lt;li&gt;thất bại hay không? anh không biết. Nhưng nếu cho anh làm lại 1 lần nữa, anh vẫn thử, vì nếu không thử, sao anh biết được kết quả, được cảm nhận, cảm xúc, đã làm. Và sống như chính con người anh&lt;&#x2F;li&gt;
&lt;li&gt;nhìn bản chất, đéo nhìn hình thức&lt;&#x2F;li&gt;
&lt;li&gt;để tán được em, được thôi, anh sẽ vượt qua cảm giác nhục nhã, thú vị đấy.&lt;&#x2F;li&gt;
&lt;li&gt;anh sẽ yêu em theo cách mà không có thằng nào từng làm&lt;&#x2F;li&gt;
&lt;li&gt;Yêu em là anh muốn và phải ép buộc bản thân để em tự do như chính con người em&lt;&#x2F;li&gt;
&lt;li&gt;sự không chắc chắn này khiến ta có động lực&lt;&#x2F;li&gt;
&lt;li&gt;em và khách hàng đầu tiên 2026 10 03. một ngày thú vị&lt;&#x2F;li&gt;
&lt;li&gt;chơi đùa với máy móc thật thú vị, khi có cảm tưởng chúng biết suy nghĩ và &quot;nói&quot;, vl&lt;&#x2F;li&gt;
&lt;li&gt;phải chăng suy nghĩ của ta đang quá hẹp hòi với em&lt;&#x2F;li&gt;
&lt;li&gt;đừng tạo áp lực cho những thứ &quot;đéo cần thiết&quot;&lt;&#x2F;li&gt;
&lt;li&gt;sự khan hiếm có thể tạo ra tình yêu và sự tôn trọng&lt;&#x2F;li&gt;
&lt;li&gt;sự kết nối giữa con người với con người (hợp gu), thật thích và không hối tiếc&lt;&#x2F;li&gt;
&lt;li&gt;chúng mày đéo chịu nhìn (và suy nghĩ) về thực tế.&lt;&#x2F;li&gt;
&lt;li&gt;đéo phải mày đéo biết làm, mà mày đéo  có công cụ (và chúng nó muốn mày phụ thuộc vào đó)&lt;&#x2F;li&gt;
&lt;li&gt;Mày cần chấp nhận rằng chúng nó luôn bảo mày đéo làm được&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;2026-09&quot;&gt;2026 09&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;x&lt;&#x2F;li&gt;
&lt;li&gt;vấn đề đấm vào mặt, và làm sao để tối ưu cái đấm đó để lần sau tốt hơn&lt;&#x2F;li&gt;
&lt;li&gt;đéo thằng nào cho ai cái gì miễn phí, à có (khả năng là lừa đảo)&lt;&#x2F;li&gt;
&lt;li&gt;tiêu chuẩn - thằng nào đặt ra, và nó là gì (chắc là dùng của ai mà mày cũng đéo biết)&lt;&#x2F;li&gt;
&lt;li&gt;khi gặp vấn đề mà mày đéo ngờ tới, thì tâm trí và cách suy nghĩ của mày quan trọng (đã giải quyết được rồi 2026 09 29)&lt;&#x2F;li&gt;
&lt;li&gt;nay em về quê, bạn kia bảo thế&lt;&#x2F;li&gt;
&lt;li&gt;xây dựng hệ thống và nối các đường dẫn, mảnh ghép ý tưởng lại với nhau&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;chúng mày chỉ giỏi kết nối (1 cách máy móc) chứ đéo tương tác&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;thực sự thì cuộc sống này có ý nghĩa gì không, hay đéo có gì ý nghĩa,mà chúng ta tự đặt ra để khiến nó có ý nghĩa&lt;&#x2F;li&gt;
&lt;li&gt;bọn mày toàn diễn giải mọi thứ phức tạp và che dấu sự đơn giản vốn có&lt;&#x2F;li&gt;
&lt;li&gt;nếu mày đéo làm thì chắc chắn đéo ai giải quyết giúp mày&lt;&#x2F;li&gt;
&lt;li&gt;thiết kế hệ thống thì quan trọng hơn làm từng việc vặt&lt;&#x2F;li&gt;
&lt;li&gt;Tối ưu tương lai có thể tốt hơn tối ưu hiện tại, và quá khứ không còn dùng nữa. Nhưng đéo có từng bước ngu (nhìn lại) này thì sẽ đéo có tương lại mà mày đang ngồi đánh giá quá khứ đã từng, thời gian ngu đó là Ý NGHĨA HIỆN TẠI&lt;&#x2F;li&gt;
&lt;li&gt;mày đéo nên chạy trốn, tránh nhìn vào, bỏ qua vấn đề mà mày nhận thấy đang cản bước. cần tỉnh thức để ghi nó lại để giải quyết&lt;&#x2F;li&gt;
&lt;li&gt;mục đích của cái này là gì, sao phải như vậy?&lt;&#x2F;li&gt;
&lt;li&gt;khi cái cốt lõi của mày tốt thì mày mới nên chỉnh cái giao diện ngoài (đéo phải ngược lại)&lt;&#x2F;li&gt;
&lt;li&gt;lúc đầu tao toàn thích sự đẹp, phức tạp... nhưng nhìn kĩ sau 1 thời gian thì tao thấy sự đơn giản là đẹp nhất, đéo chán&lt;&#x2F;li&gt;
&lt;li&gt;nhiều lúc cảm thấy trống rỗng, chán, một mình&lt;&#x2F;li&gt;
&lt;li&gt;tầm nhìn đôi khi cần đéo thoả hiệp&lt;&#x2F;li&gt;
&lt;li&gt;thời điểm quái quỷ gì đây, vãi thật&lt;&#x2F;li&gt;
&lt;li&gt;bước nghiệm thu là 1 hành trình &lt;strong&gt;đau&lt;&#x2F;strong&gt;, nhưng sau đó thì tuyệt&lt;&#x2F;li&gt;
&lt;li&gt;Làm những gì hữu ích và quên mẹ nó đi&lt;&#x2F;li&gt;
&lt;li&gt;T không giỏi nhưng tao biết mình ngu, và hạn hẹp&lt;&#x2F;li&gt;
&lt;li&gt;Dọn dẹp là cơ hội để phát triển và mở ra những khoảng trống mới và ý tưởng&lt;&#x2F;li&gt;
&lt;li&gt;Nhiều thằng gặp nhau chỉ nói những thứ vớ vẩn, chẳng có ý nghĩa mẹ gì&lt;&#x2F;li&gt;
&lt;li&gt;Thà gặp và tin ở ngoài hơn là nghe những kẻ đạo đức giả trên kia&lt;&#x2F;li&gt;
&lt;li&gt;Tặng em kẹo, mong em vui&lt;&#x2F;li&gt;
&lt;li&gt;Suy nghĩ, cảm nhận và ... nhận ra sự sống&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Syncing One Obsidian Vault Across Android, a Laptop, and a Home Server</title>
        <published>2026-10-03T00:00:00+00:00</published>
        <updated>2026-10-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/obsidian-live-sync-across-devices/"/>
        <id>https://quoc.app/write/obsidian-live-sync-across-devices/</id>
        
        <content type="html" xml:base="https://quoc.app/write/obsidian-live-sync-across-devices/">&lt;div lang=&quot;en&quot;&gt;
&lt;p&gt;I wanted the same Obsidian notes across three devices: a laptop where I edit in VSCodium, a browser editor on a home server, and an Android phone. The laptop setup already worked. The phone was the awkward part.&lt;&#x2F;p&gt;
&lt;p&gt;Adding Syncthing to the phone looked like the shortest route. It was also the wrong one. The Obsidian plugin and Syncthing would both be watching the same mobile folder. One edit could become two competing updates, then a conflict file, then a second cleanup job.&lt;&#x2F;p&gt;
&lt;p&gt;I kept Syncthing on the laptop and gave Android a separate route through CouchDB. The server folder stayed where the browser editor expected it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-layout&quot;&gt;The layout&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Laptop:&lt;&#x2F;strong&gt; VSCodium edits a local vault folder. Syncthing sends those file changes to the home server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Browser editor:&lt;&#x2F;strong&gt; WebObsidian reads and writes the real vault folder on that server.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Android:&lt;&#x2F;strong&gt; Obsidian Mobile keeps its local copy for offline work. The Self-hosted LiveSync plugin replicates it with CouchDB over a private HTTPS route.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Home server:&lt;&#x2F;strong&gt; &lt;code&gt;livesync-cli&lt;&#x2F;code&gt; runs as a daemon and mirrors the CouchDB database with the same server-side vault folder.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;CouchDB is the phone&#x27;s sync hub. It does not replace the Markdown folder. The folder remains the shared working copy for the browser editor and laptop.&lt;&#x2F;p&gt;
&lt;figure class=&quot;diagram-figure&quot;&gt;
  &lt;svg viewBox=&quot;0 0 960 480&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; role=&quot;img&quot; aria-labelledby=&quot;vault-sync-title vault-sync-desc&quot; style=&quot;width:100%;height:auto;display:block;&quot;&gt;
  &lt;title id=&quot;vault-sync-title&quot;&gt;One Obsidian vault across three devices&lt;&#x2F;title&gt;
  &lt;desc id=&quot;vault-sync-desc&quot;&gt;Architecture diagram showing a laptop running VSCodium syncing a server-side vault folder through Syncthing, a WebObsidian browser editor reading and writing the same folder, a livesync-cli daemon mirroring the folder with CouchDB, and an Android phone running Obsidian Mobile connected to CouchDB over a private tailnet HTTPS route.&lt;&#x2F;desc&gt;
  &lt;defs&gt;
    &lt;marker id=&quot;vs-arrow&quot; markerWidth=&quot;8&quot; markerHeight=&quot;6&quot; refX=&quot;7&quot; refY=&quot;3&quot; orient=&quot;auto&quot;&gt;&lt;polygon points=&quot;0 0, 8 3, 0 6&quot; fill=&quot;#4f5d75&quot;&#x2F;&gt;&lt;&#x2F;marker&gt;
  &lt;&#x2F;defs&gt;

  &lt;!-- Zone: home server (drawn before arrows and nodes) --&gt;
  &lt;rect x=&quot;240&quot; y=&quot;108&quot; width=&quot;472&quot; height=&quot;344&quot; rx=&quot;8&quot;
        fill=&quot;rgba(45,49,66,0.02)&quot; stroke=&quot;rgba(45,49,66,0.10)&quot; stroke-width=&quot;0.8&quot;&#x2F;&gt;
  &lt;rect x=&quot;428&quot; y=&quot;112&quot; width=&quot;96&quot; height=&quot;12&quot; rx=&quot;2&quot; fill=&quot;#ffffff&quot;&#x2F;&gt;
  &lt;text x=&quot;476&quot; y=&quot;121&quot; fill=&quot;rgba(45,49,66,0.40)&quot; font-size=&quot;7&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot; letter-spacing=&quot;0.14em&quot;&gt;HOME SERVER&lt;&#x2F;text&gt;

  &lt;!-- Arrows first (behind boxes) --&gt;
  &lt;line x1=&quot;184&quot; y1=&quot;272&quot; x2=&quot;264&quot; y2=&quot;272&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1.2&quot; marker-end=&quot;url(#vs-arrow)&quot;&#x2F;&gt;
  &lt;line x1=&quot;352&quot; y1=&quot;196&quot; x2=&quot;352&quot; y2=&quot;240&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1.2&quot; marker-start=&quot;url(#vs-arrow)&quot; marker-end=&quot;url(#vs-arrow)&quot;&#x2F;&gt;
  &lt;line x1=&quot;440&quot; y1=&quot;272&quot; x2=&quot;488&quot; y2=&quot;272&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1.2&quot; marker-start=&quot;url(#vs-arrow)&quot; marker-end=&quot;url(#vs-arrow)&quot;&#x2F;&gt;
  &lt;line x1=&quot;588&quot; y1=&quot;304&quot; x2=&quot;588&quot; y2=&quot;372&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1.2&quot; marker-start=&quot;url(#vs-arrow)&quot; marker-end=&quot;url(#vs-arrow)&quot;&#x2F;&gt;
  &lt;line x1=&quot;696&quot; y1=&quot;404&quot; x2=&quot;768&quot; y2=&quot;404&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1.2&quot; marker-start=&quot;url(#vs-arrow)&quot; marker-end=&quot;url(#vs-arrow)&quot;&#x2F;&gt;

  &lt;!-- Arrow labels --&gt;
  &lt;rect x=&quot;194&quot; y=&quot;252&quot; width=&quot;64&quot; height=&quot;12&quot; rx=&quot;2&quot; fill=&quot;#ffffff&quot;&#x2F;&gt;
  &lt;text x=&quot;226&quot; y=&quot;262&quot; fill=&quot;#4f5d75&quot; font-size=&quot;8&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot; letter-spacing=&quot;0.08em&quot;&gt;SYNCTHING&lt;&#x2F;text&gt;

  &lt;rect x=&quot;560&quot; y=&quot;330&quot; width=&quot;56&quot; height=&quot;12&quot; rx=&quot;2&quot; fill=&quot;#ffffff&quot;&#x2F;&gt;
  &lt;text x=&quot;588&quot; y=&quot;339&quot; fill=&quot;#4f5d75&quot; font-size=&quot;8&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot; letter-spacing=&quot;0.08em&quot;&gt;REPLICATE&lt;&#x2F;text&gt;

  &lt;rect x=&quot;692&quot; y=&quot;384&quot; width=&quot;80&quot; height=&quot;12&quot; rx=&quot;2&quot; fill=&quot;#ffffff&quot;&#x2F;&gt;
  &lt;text x=&quot;732&quot; y=&quot;394&quot; fill=&quot;#4f5d75&quot; font-size=&quot;8&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot; letter-spacing=&quot;0.08em&quot;&gt;TAILNET HTTPS&lt;&#x2F;text&gt;

  &lt;!-- Nodes --&gt;
  &lt;!-- Laptop (input) --&gt;
  &lt;rect x=&quot;48&quot; y=&quot;248&quot; width=&quot;136&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;rgba(79,93,117,0.10)&quot; stroke=&quot;#7a8399&quot; stroke-width=&quot;1&quot;&#x2F;&gt;
  &lt;text x=&quot;116&quot; y=&quot;269&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;Laptop&lt;&#x2F;text&gt;
  &lt;text x=&quot;116&quot; y=&quot;284&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;VSCODIUM&lt;&#x2F;text&gt;

  &lt;!-- WebObsidian (external) --&gt;
  &lt;rect x=&quot;272&quot; y=&quot;140&quot; width=&quot;160&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;rgba(45,49,66,0.03)&quot; stroke=&quot;rgba(45,49,66,0.30)&quot; stroke-width=&quot;1&quot;&#x2F;&gt;
  &lt;text x=&quot;352&quot; y=&quot;161&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;WebObsidian&lt;&#x2F;text&gt;
  &lt;text x=&quot;352&quot; y=&quot;176&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;BROWSER EDITOR&lt;&#x2F;text&gt;

  &lt;!-- Vault folder (store) --&gt;
  &lt;rect x=&quot;272&quot; y=&quot;248&quot; width=&quot;160&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;rgba(45,49,66,0.05)&quot; stroke=&quot;#4f5d75&quot; stroke-width=&quot;1&quot;&#x2F;&gt;
  &lt;text x=&quot;352&quot; y=&quot;269&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;Vault folder&lt;&#x2F;text&gt;
  &lt;text x=&quot;352&quot; y=&quot;284&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;MARKDOWN ON DISK&lt;&#x2F;text&gt;

  &lt;!-- livesync-cli daemon (backend) --&gt;
  &lt;rect x=&quot;496&quot; y=&quot;248&quot; width=&quot;184&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;#ffffff&quot; stroke=&quot;#2d3142&quot; stroke-width=&quot;1&quot;&#x2F;&gt;
  &lt;text x=&quot;588&quot; y=&quot;269&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;livesync-cli daemon&lt;&#x2F;text&gt;
  &lt;text x=&quot;588&quot; y=&quot;284&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;WATCH + MIRROR&lt;&#x2F;text&gt;

  &lt;!-- CouchDB (focal) --&gt;
  &lt;rect x=&quot;496&quot; y=&quot;380&quot; width=&quot;184&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;rgba(17,17,17,0.08)&quot; stroke=&quot;#111111&quot; stroke-width=&quot;1.2&quot;&#x2F;&gt;
  &lt;text x=&quot;588&quot; y=&quot;401&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;CouchDB&lt;&#x2F;text&gt;
  &lt;text x=&quot;588&quot; y=&quot;416&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;PHONE SYNC HUB&lt;&#x2F;text&gt;

  &lt;!-- Android (external) --&gt;
  &lt;rect x=&quot;776&quot; y=&quot;380&quot; width=&quot;152&quot; height=&quot;48&quot; rx=&quot;6&quot; fill=&quot;rgba(45,49,66,0.03)&quot; stroke=&quot;rgba(45,49,66,0.30)&quot; stroke-width=&quot;1&quot;&#x2F;&gt;
  &lt;text x=&quot;852&quot; y=&quot;401&quot; fill=&quot;#2d3142&quot; font-size=&quot;12&quot; font-weight=&quot;600&quot; font-family=&quot;&#x27;Geist&#x27;,-apple-system,&#x27;Segoe UI&#x27;,sans-serif&quot; text-anchor=&quot;middle&quot;&gt;Android&lt;&#x2F;text&gt;
  &lt;text x=&quot;852&quot; y=&quot;416&quot; fill=&quot;#7a8399&quot; font-size=&quot;9&quot; font-family=&quot;&#x27;Geist Mono&#x27;,&#x27;Cascadia Mono&#x27;,Consolas,monospace&quot; text-anchor=&quot;middle&quot;&gt;OBSIDIAN MOBILE&lt;&#x2F;text&gt;
&lt;&#x2F;svg&gt;

&lt;&#x2F;figure&gt;
&lt;p&gt;Syncthing keeps the laptop-to-server lane. LiveSync connects Android to CouchDB, and the daemon joins CouchDB to the server folder. Do not add a second sync engine to the same Android vault directory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;decide-what-belongs-on-the-phone-first&quot;&gt;Decide what belongs on the phone first&lt;&#x2F;h2&gt;
&lt;p&gt;A vault can hold active notes, old exports, scans, videos, and other files that are useful on a desktop but unnecessary on a phone. If the entire archive is copied into CouchDB, the phone will fetch it too. That means more storage, more network traffic, more database revisions, and more private material on a mobile device.&lt;&#x2F;p&gt;
&lt;p&gt;I kept the root &lt;code&gt;archive&#x2F;&lt;&#x2F;code&gt; folder outside mobile sync. I also left hidden files and device-specific Obsidian settings out. The exact ignore syntax belongs to the pinned LiveSync CLI release, so read that release&#x27;s &lt;code&gt;IgnoreRules.ts&lt;&#x2F;code&gt; instead of assuming every pattern follows Git&#x27;s &lt;code&gt;.gitignore&lt;&#x2F;code&gt; rules. In the CLI source used for this setup, a path pattern such as &lt;code&gt;archive&#x2F;**&lt;&#x2F;code&gt; applies to the root &lt;code&gt;archive&lt;&#x2F;code&gt; path; a trailing-slash directory pattern can match directories at any depth. Negation patterns are not supported there.&lt;&#x2F;p&gt;
&lt;p&gt;A small example looks like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;archive&amp;#x2F;**
.obsidian&amp;#x2F;
.livesync&amp;#x2F;
.stfolder
.stignore
.stversions&amp;#x2F;
*.sync-conflict-*
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The rule for &lt;code&gt;archive&#x2F;&lt;&#x2F;code&gt; is a data decision, not a cosmetic filter. A note on the phone can still contain a link to a file under an excluded folder, but that image or attachment will not be available on the phone. If only a few archived images are needed, copy those files into a synced folder such as &lt;code&gt;attachments&#x2F;mobile&#x2F;&lt;&#x2F;code&gt; and update the links. Do not enable the whole archive just to retrieve one picture.&lt;&#x2F;p&gt;
&lt;p&gt;For new attachments created on Android, Obsidian&#x27;s &lt;strong&gt;Files &amp;amp; Links&lt;&#x2F;strong&gt; settings can place them in a folder inside the vault, for example &lt;code&gt;attachments&#x2F;mobile&#x2F;&lt;&#x2F;code&gt;. This keeps the vault root tidy while still allowing LiveSync to transfer the files. A path outside the vault is not an attachment location that LiveSync can manage. This setting affects new attachments only; it does not move existing files or new notes.&lt;&#x2F;p&gt;
&lt;p&gt;Before widening the sync scope, inventory file sizes and filenames that may represent credentials or personal records. Synchronization is not a backup, and an Android copy expands the number of places where data lives.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;put-couchdb-behind-a-private-https-route&quot;&gt;Put CouchDB behind a private HTTPS route&lt;&#x2F;h2&gt;
&lt;p&gt;Install CouchDB on the home server with persistent data storage and a strong admin credential. Publish its port only on loopback, then expose it to the phone through a private VPN&#x27;s HTTPS proxy. For Tailscale, the &lt;code&gt;tailscale serve&lt;&#x2F;code&gt; command provides the private HTTPS endpoint; see the &lt;a href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;docs&#x2F;reference&#x2F;tailscale-cli&#x2F;serve&quot;&gt;Tailscale Serve reference&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A Compose skeleton should resemble this. It is illustrative, not a drop-in production file. Pin the image and add the resource limits, permissions, backup paths, and host-specific protections required by your server.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;services:
  couchdb:
    image: couchdb:&amp;lt;pinned-version-or-digest&amp;gt;
    ports:
      - &amp;quot;127.0.0.1:5984:5984&amp;quot;
    environment:
      COUCHDB_USER: &amp;quot;${COUCHDB_USER:?required}&amp;quot;
      COUCHDB_PASSWORD: &amp;quot;${COUCHDB_PASSWORD:?required}&amp;quot;
    volumes:
      - .&amp;#x2F;couchdb-data:&amp;#x2F;opt&amp;#x2F;couchdb&amp;#x2F;data
      - .&amp;#x2F;couchdb-etc:&amp;#x2F;opt&amp;#x2F;couchdb&amp;#x2F;etc&amp;#x2F;local.d
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Mount the configuration directory writable. Some CouchDB image entrypoints modify a file in that directory when they provision the admin account. A read-only bind of one config file can turn a normal first boot into a restart loop.&lt;&#x2F;p&gt;
&lt;p&gt;For a single-node server, the relevant settings include single-node mode, authenticated access, and CORS for the Obsidian mobile origins. Keep the values in a protected config file and check the &lt;a href=&quot;https:&#x2F;&#x2F;docs.couchdb.org&#x2F;en&#x2F;stable&#x2F;install&#x2F;docker.html&quot;&gt;CouchDB Docker guide&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.couchdb.org&#x2F;en&#x2F;stable&#x2F;config&#x2F;http.html&quot;&gt;HTTP&#x2F;CORS configuration reference&lt;&#x2F;a&gt; for the version you deploy.&lt;&#x2F;p&gt;
&lt;p&gt;A minimal example of the settings used in this setup is below. Review the limits and allowed origins against the plugin release you actually install; do not paste this over an existing CouchDB config without checking it first.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[couchdb]
single_node = true
max_document_size = 50000000

[chttpd]
require_valid_user = true
enable_cors = true
max_http_request_size = 52428800

[chttpd_auth]
require_valid_user = true

[httpd]
WWW-Authenticate = Basic realm=&amp;quot;couchdb&amp;quot;
enable_cors = true

[cors]
origins = app:&amp;#x2F;&amp;#x2F;obsidian.md, capacitor:&amp;#x2F;&amp;#x2F;localhost, http:&amp;#x2F;&amp;#x2F;localhost
credentials = true
methods = GET,PUT,POST,HEAD,DELETE
headers = accept, authorization, content-type, origin, referer
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The mobile plugin sends browser-style CORS requests. CORS does not authenticate a user. Keep CouchDB authentication enabled, verify an unauthenticated request gets &lt;code&gt;401&lt;&#x2F;code&gt;, and verify an authenticated request succeeds. Test the CORS preflight through the private HTTPS hostname from another tailnet device. A self-request from the server to its own VPN hostname can fail because of hairpin routing even when a laptop or phone can reach it.&lt;&#x2F;p&gt;
&lt;p&gt;Create the database through CouchDB&#x27;s HTTP API. Treat &lt;code&gt;201 Created&lt;&#x2F;code&gt; and &lt;code&gt;412 Precondition Failed&lt;&#x2F;code&gt; as the normal create-or-already-exists outcomes. Keep the actual password out of logs, shell history, screenshots, and chat.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bridge-the-database-to-the-real-vault-folder&quot;&gt;Bridge the database to the real vault folder&lt;&#x2F;h2&gt;
&lt;p&gt;Build the headless CLI from an exact upstream tag or commit. Do not build from &lt;code&gt;latest&lt;&#x2F;code&gt; and assume the setup flags stay stable. The &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&#x2F;blob&#x2F;1.0.34&#x2F;src&#x2F;apps&#x2F;cli&#x2F;README.md&quot;&gt;LiveSync CLI README&lt;&#x2F;a&gt; documents its database path, vault path, &lt;code&gt;daemon&lt;&#x2F;code&gt;, &lt;code&gt;mirror&lt;&#x2F;code&gt;, and &lt;code&gt;ls&lt;&#x2F;code&gt; commands.&lt;&#x2F;p&gt;
&lt;p&gt;The database path and the Markdown vault path are different things. The database directory holds local database state and settings. The vault path is the actual folder served by the browser editor and watched by Syncthing. A Compose service can make that split explicit:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;services:
  livesync:
    image: livesync-cli:&amp;lt;same-pinned-release&amp;gt;
    environment:
      LIVESYNC_DB_PATH: &amp;#x2F;data
    volumes:
      - .&amp;#x2F;cli-db:&amp;#x2F;data
      - &amp;#x2F;path&amp;#x2F;to&amp;#x2F;canonical-vault:&amp;#x2F;vault:rw
    command: [&amp;quot;daemon&amp;quot;, &amp;quot;-V&amp;quot;, &amp;quot;&amp;#x2F;vault&amp;quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Match the container UID&#x2F;GID to the owner of the mounted vault. Add read-only root filesystem, dropped capabilities, resource limits, and other hardening where the image permits it. Do not publish a port for the CLI container.&lt;&#x2F;p&gt;
&lt;p&gt;Run &lt;code&gt;daemon&lt;&#x2F;code&gt; as the long-lived service. &lt;code&gt;mirror&lt;&#x2F;code&gt; is a one-shot scan that exits. The initial daemon scan also does not infer every deletion from a missing file; after a container restart, a file deleted during the gap can reappear in the folder. The LiveSync CLI README describes this behavior and the differences between a file path and the local database path.&lt;&#x2F;p&gt;
&lt;p&gt;Bootstrap the local settings and remote connection once. Verify that the settings are marked configured and the selected database name matches the CouchDB database before starting the long-lived service. Connection-string syntax has changed across implementations; follow the parser and docs for the exact release you pinned. In the CLI release used for this setup, the database name was supplied as a &lt;code&gt;db&lt;&#x2F;code&gt; query parameter. Do not assume a URL path and a query parameter mean the same thing.&lt;&#x2F;p&gt;
&lt;p&gt;After creating &lt;code&gt;.livesync&#x2F;ignore&lt;&#x2F;code&gt;, restart the daemon so it reloads the rules. Wait for the remote document count to settle over more than one observation, but do not compare that count directly with the number of files. LiveSync splits a large file into multiple chunk documents.&lt;&#x2F;p&gt;
&lt;p&gt;If you need a file-list probe against the CLI&#x27;s local database, stop the daemon first. Running the CLI against the same local database while the daemon has it open can hit a LevelDB lock. Restart the service after the probe, even when the probe fails.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;connect-android-without-reusing-the-old-syncthing-copy&quot;&gt;Connect Android without reusing the old Syncthing copy&lt;&#x2F;h2&gt;
&lt;p&gt;On the Android device, remove only the old vault folder from the Syncthing app. Leave the laptop and server peers alone. Keep the old local copy until the new setup passes its tests; it is a fallback, not the new LiveSync vault.&lt;&#x2F;p&gt;
&lt;p&gt;Create a new, empty Obsidian vault on the phone. Install the Self-hosted LiveSync community plugin, then configure the database endpoint as an HTTPS URL reachable only inside the private tailnet, for example &lt;code&gt;https:&#x2F;&#x2F;&amp;lt;server&amp;gt;.&amp;lt;tailnet&amp;gt;.ts.net&#x2F;&amp;lt;database&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Choose &lt;strong&gt;overwrite local files with remote files&lt;&#x2F;strong&gt; only when the phone vault is genuinely empty. If there are local-only notes worth keeping, stop and back them up or merge them deliberately first. When the plugin finds multiple saved remote profiles, verify the active connection instead of repeating the wizard and creating more profiles.&lt;&#x2F;p&gt;
&lt;p&gt;Then open &lt;strong&gt;Settings → Community plugins → Self-hosted LiveSync → Sync Settings&lt;&#x2F;strong&gt;. Select the &lt;code&gt;LiveSync&lt;&#x2F;code&gt; preset and tap &lt;strong&gt;Apply&lt;&#x2F;strong&gt;. Reopen the settings and make sure &lt;strong&gt;Sync Mode&lt;&#x2F;strong&gt; actually reads &lt;code&gt;LiveSync&lt;&#x2F;code&gt;. Selecting a preset in a menu without applying it leaves the old mode in place.&lt;&#x2F;p&gt;
&lt;p&gt;This was the failure that made my first setup look finished while it was not. The initial download completed. A manual &lt;strong&gt;Sync now&lt;&#x2F;strong&gt; also moved files. But the selected mode was still &lt;code&gt;On events&lt;&#x2F;code&gt;, so automatic remote updates did not behave like a continuous LiveSync connection. Applying the &lt;code&gt;LiveSync&lt;&#x2F;code&gt; preset fixed the mode. A one-shot sync button is a poor test for continuous synchronization.&lt;&#x2F;p&gt;
&lt;p&gt;For the plugin&#x27;s own-server instructions, start with the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&#x2F;blob&#x2F;1.0.34&#x2F;docs&#x2F;setup_own_server.md&quot;&gt;Self-hosted LiveSync setup guide&lt;&#x2F;a&gt;. Keep the plugin&#x27;s end-to-end encryption setting as an explicit security decision. HTTPS protects traffic in transit; CouchDB authentication limits access; neither replaces end-to-end encryption. If E2EE is disabled, the server can read the notes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verify-the-whole-path-not-just-the-green-icon&quot;&gt;Verify the whole path, not just the green icon&lt;&#x2F;h2&gt;
&lt;p&gt;Use disposable canary files with unique names. Do not test by repeatedly editing a valuable note.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create a small note on Android. Confirm the file appears in the server vault folder, then check it from the laptop or browser editor.&lt;&#x2F;li&gt;
&lt;li&gt;Create a second note on the server folder. Confirm the Android vault receives it without pressing &lt;strong&gt;Sync now&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Edit an existing test note in the browser editor. Wait for the server file to change, then confirm the phone receives the same content.&lt;&#x2F;li&gt;
&lt;li&gt;Create and edit a note while Android is offline. Reconnect and verify both sides converge without losing text.&lt;&#x2F;li&gt;
&lt;li&gt;Delete a disposable note from the phone and check that its server file disappears.&lt;&#x2F;li&gt;
&lt;li&gt;Close Obsidian, change a server note, reopen Obsidian, and verify catch-up.&lt;&#x2F;li&gt;
&lt;li&gt;Restart CouchDB and check that the daemon and phone reconnect.&lt;&#x2F;li&gt;
&lt;li&gt;Change networks and confirm the phone reconnects before relying on it away from home.&lt;&#x2F;li&gt;
&lt;li&gt;Open the phone&#x27;s file list and confirm excluded folders are absent by design.&lt;&#x2F;li&gt;
&lt;li&gt;Compare hashes for a test file after conflict resolution. Do not assume a completed fetch means two live copies are identical.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A useful test result has a source, a destination, a unique marker, and a time window. “The sync icon looked fine” is not enough. Record which hop failed: phone to CouchDB, CouchDB to the server folder, or server folder to the browser&#x2F;laptop.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backups-and-conflict-policy&quot;&gt;Backups and conflict policy&lt;&#x2F;h2&gt;
&lt;p&gt;Syncthing and LiveSync replicate changes. If a bad edit or delete reaches every peer, synchronization can spread the mistake too. Keep an independent, off-host backup and test restoring it before trusting the setup with irreplaceable records.&lt;&#x2F;p&gt;
&lt;p&gt;Avoid simultaneous edits to the same file from the phone, browser editor, and laptop. LiveSync keeps conflicting revisions, and the plugin can sometimes merge text. That is a recovery aid, not a reason to invite conflicts. After a merge, compare the resulting file with the intended content.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-setting-that-made-automatic-sync-work&quot;&gt;The setting that made automatic sync work&lt;&#x2F;h2&gt;
&lt;p&gt;The first fetch had completed, and pressing &lt;code&gt;Sync now&lt;&#x2F;code&gt; moved files. Automatic updates still did not arrive. The phone was left in &lt;code&gt;On events&lt;&#x2F;code&gt; mode because I had selected the &lt;code&gt;LiveSync&lt;&#x2F;code&gt; preset but had not tapped &lt;code&gt;Apply&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After applying the preset, I created one canary on the phone and one on the server. Both appeared on the other side without pressing &lt;code&gt;Sync now&lt;&#x2F;code&gt;. That is the check I would repeat on a new phone before trusting the setup.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&quot;&gt;Self-hosted LiveSync project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&#x2F;blob&#x2F;1.0.34&#x2F;docs&#x2F;setup_own_server.md&quot;&gt;CouchDB setup guide for the LiveSync plugin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&#x2F;blob&#x2F;1.0.34&#x2F;src&#x2F;apps&#x2F;cli&#x2F;README.md&quot;&gt;LiveSync CLI reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vrtmrz&#x2F;obsidian-livesync&#x2F;blob&#x2F;1.0.34&#x2F;src&#x2F;apps&#x2F;cli&#x2F;serviceModules&#x2F;IgnoreRules.ts&quot;&gt;LiveSync CLI ignore-rule implementation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.couchdb.org&#x2F;en&#x2F;stable&#x2F;install&#x2F;docker.html&quot;&gt;CouchDB Docker installation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.couchdb.org&#x2F;en&#x2F;stable&#x2F;config&#x2F;http.html&quot;&gt;CouchDB HTTP and CORS settings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tailscale.com&#x2F;docs&#x2F;reference&#x2F;tailscale-cli&#x2F;serve&quot;&gt;Tailscale Serve CLI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.syncthing.net&#x2F;users&#x2F;faq.html#why-are-there-conflict-files&quot;&gt;Syncthing conflict-file FAQ&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;obsidian.md&#x2F;help&#x2F;Files+and+folders&#x2F;Manage+attachments&quot;&gt;Obsidian attachment settings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;small&gt;&lt;em&gt;AI assistance: GPT-6 Luna (OpenAI Codex) and GLM-5.3 Flash (Z.ai) assisted in preparing this article. The author is responsible for the final published version.&lt;&#x2F;em&gt;&lt;&#x2F;small&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Other Tools</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/share/other-tools/"/>
        <id>https://quoc.app/share/other-tools/</id>
        
        <content type="html" xml:base="https://quoc.app/share/other-tools/">&lt;p&gt;Table of Contents:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quoc.app&#x2F;share&#x2F;other-tools&#x2F;#spamblocker&quot;&gt;SpamBlocker&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quoc.app&#x2F;share&#x2F;other-tools&#x2F;#usb-boot&quot;&gt;USB Boot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quoc.app&#x2F;share&#x2F;other-tools&#x2F;#bluetooth-keyboard&quot;&gt;Bluetooth Keyboard&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quoc.app&#x2F;share&#x2F;other-tools&#x2F;#icon-design&quot;&gt;Icon Design&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quoc.app&#x2F;share&#x2F;other-tools&#x2F;#paypal&quot;&gt;PayPal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;spamblocker&quot;&gt;SpamBlocker&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;huong-dan-dung-spamblocker-android&quot;&gt;Hướng dẫn dùng SpamBlocker (Android)&lt;&#x2F;h3&gt;
&lt;p&gt;SpamBlocker là ứng dụng mã nguồn mở giúp chặn cuộc gọi và tin nhắn spam, đặc biệt mạnh khi chặn theo dải số và regex.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;1-cai-dat-cap-quyen&quot;&gt;1. Cài đặt &amp;amp; cấp quyền&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;Cài SpamBlocker từ F-Droid hoặc file APK&#x2F;GitHub của tác giả.&lt;&#x2F;li&gt;
&lt;li&gt;Mở app lần đầu, bật &lt;strong&gt;Enable&lt;&#x2F;strong&gt; ở góc trên cùng.&lt;&#x2F;li&gt;
&lt;li&gt;Cấp đầy đủ quyền:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;Quyền Điện thoại (Phone)&lt;&#x2F;li&gt;
&lt;li&gt;Quyền Tin nhắn (nếu muốn chặn SMS)&lt;&#x2F;li&gt;
&lt;li&gt;Quyền Thông báo (Notifications)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Đảm bảo app không bị tối ưu pin quá mức (Battery optimization) để không bị hệ thống &quot;giết&quot; ngầm.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Nếu không cấp đủ quyền, app sẽ không chặn được hoặc chỉ hoạt động lúc đang mở.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251206112112.png&quot; alt=&quot;pasted image 20251206112112&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;2-cac-khai-niem-chinh-tren-man-hinh-settings&quot;&gt;2. Các khái niệm chính trên màn hình Settings&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Contacts&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Bật nếu muốn &lt;strong&gt;luôn cho phép số trong danh bạ&lt;&#x2F;strong&gt; (whitelist tự động).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Repeated Call&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Chặn số gọi tới liên tục trong một khoảng thời gian (chống quấy rối).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Block Type&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reject&lt;&#x2F;strong&gt;: Từ chối cuộc gọi (có thể vẫn đổ 1–2 tiếng chuông ngắn rồi cúp).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Silence&lt;&#x2F;strong&gt;: Chặn im lặng, thường không thấy chuông.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Answer + Hangup&lt;&#x2F;strong&gt;: Tự động nghe rồi cúp, đảm bảo cắt cuộc gọi nhanh.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Notification&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Chọn kiểu thông báo khi có cuộc gọi&#x2F;SMS bị chặn (hoặc tắt hẳn nếu muốn &quot;vô tri&quot;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251206112302.png&quot; alt=&quot;pasted image 20251206112302&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;3-number-rules-chan-theo-so-regex&quot;&gt;3. Number Rules – chặn theo số&#x2F;regex&lt;&#x2F;h4&gt;
&lt;h5 id=&quot;3-1-tao-rule-moi&quot;&gt;3.1. Tạo rule mới&lt;&#x2F;h5&gt;
&lt;ol&gt;
&lt;li&gt;Vào &lt;strong&gt;Number Rules&lt;&#x2F;strong&gt; → bấm &lt;strong&gt;New&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Ở ô &lt;strong&gt;Phone Number&lt;&#x2F;strong&gt;, nhập mẫu cần chặn:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;Chặn &lt;strong&gt;chính xác 1 số&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Dạng regex: &lt;code&gt;^0839221196$&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Hoặc đơn giản chỉ nhập &lt;code&gt;0839221196&lt;&#x2F;code&gt; (ít rủi ro hơn khi không hiểu sâu regex).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Chặn &lt;strong&gt;dải số&lt;&#x2F;strong&gt; (ví dụ dải 0839xxx…):
&lt;ul&gt;
&lt;li&gt;Nhập: &lt;code&gt;^0839.*&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Điền &lt;strong&gt;Description&lt;&#x2F;strong&gt; (mô tả) cho dễ nhớ, ví dụ: &lt;code&gt;anh hoang&lt;&#x2F;code&gt;, &lt;code&gt;telemarketing&lt;&#x2F;code&gt;, &lt;code&gt;ngân hàng spam&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251206112526.png&quot; alt=&quot;pasted image 20251206112526&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h5 id=&quot;3-2-regex-flags-co-regex&quot;&gt;3.2. Regex Flags (cờ regex)&lt;&#x2F;h5&gt;
&lt;p&gt;Trong popup &lt;strong&gt;Regex Flags&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raw Number&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Nếu BẬT: so khớp với số dạng &quot;thô&quot;.&lt;&#x2F;li&gt;
&lt;li&gt;Nếu TẮT: app có thể bỏ số 0 đầu, đổi sang +84…, nên pattern cần linh hoạt.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ignore Country Code&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Dùng nếu bạn muốn chặn cả dạng &lt;code&gt;0839221196&lt;&#x2F;code&gt; lẫn &lt;code&gt;+84839221196&lt;&#x2F;code&gt; mà không phải viết 2 pattern.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Case Sensitive&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Với số điện thoại thường không cần quan tâm, có thể bỏ qua.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Kinh nghiệm đơn giản:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Nếu chặn &lt;strong&gt;1 số cụ thể&lt;&#x2F;strong&gt; → chỉ nhập số thẳng, không cần &lt;code&gt;^&lt;&#x2F;code&gt; và &lt;code&gt;$&lt;&#x2F;code&gt;, không bật Raw Number.&lt;&#x2F;li&gt;
&lt;li&gt;Nếu chặn &lt;strong&gt;dải số&lt;&#x2F;strong&gt; → dùng regex &lt;code&gt;^….*&lt;&#x2F;code&gt; và test kỹ trước khi lưu.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;4-thiet-lap-hanh-vi-chan-cho-rule&quot;&gt;4. Thiết lập hành vi chặn cho rule&lt;&#x2F;h4&gt;
&lt;p&gt;Trong cửa sổ rule:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Apply to&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Tick &lt;strong&gt;Call&lt;&#x2F;strong&gt; để chặn cuộc gọi.&lt;&#x2F;li&gt;
&lt;li&gt;Tick &lt;strong&gt;SMS&lt;&#x2F;strong&gt; để chặn tin nhắn.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Type&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Chọn &lt;strong&gt;Block&lt;&#x2F;strong&gt; (chặn) — đừng nhầm với &lt;strong&gt;Allow&lt;&#x2F;strong&gt; (cho phép).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Block Type&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Gợi ý: chọn &lt;strong&gt;Silence&lt;&#x2F;strong&gt; để chặn im lặng, không bị giật mình vì chuông.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Notification&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Chọn &quot;X&quot; nếu không muốn thông báo.&lt;&#x2F;li&gt;
&lt;li&gt;Hoặc chọn kiểu thông báo phù hợp nếu muốn theo dõi log chặn.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Schedule&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;Có thể bật nếu muốn rule này chỉ hoạt động theo khung giờ nhất định (ví dụ giờ làm việc).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Đừng quên bấm &lt;strong&gt;Save&lt;&#x2F;strong&gt; ở góc dưới để lưu rule.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;5-kiem-tra-rule-bang-nut-test&quot;&gt;5. Kiểm tra rule bằng nút Test&lt;&#x2F;h4&gt;
&lt;p&gt;SpamBlocker có nút &lt;strong&gt;Test&lt;&#x2F;strong&gt; cho từng rule:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Mở rule vừa tạo.&lt;&#x2F;li&gt;
&lt;li&gt;Bấm icon &lt;strong&gt;Test&lt;&#x2F;strong&gt; (thường là biểu tượng giống kính lúp&#x2F;kiểm tra).&lt;&#x2F;li&gt;
&lt;li&gt;Nhập một số giả lập (hoặc chính số bạn muốn chặn) rồi chạy test.&lt;&#x2F;li&gt;
&lt;li&gt;Nếu test báo &lt;strong&gt;matched&lt;&#x2F;strong&gt; → rule hoạt động đúng.&lt;&#x2F;li&gt;
&lt;li&gt;Nếu không match:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;Kiểm tra lại pattern (regex có đúng không).&lt;&#x2F;li&gt;
&lt;li&gt;Kiểm tra lại cờ &lt;strong&gt;Raw Number&lt;&#x2F;strong&gt; &#x2F; &lt;strong&gt;Ignore Country Code&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;6-mot-so-vi-du-pattern-huu-ich&quot;&gt;6. Một số ví dụ pattern hữu ích&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Chặn &lt;strong&gt;một số cụ thể&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0839221196&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Chặn &lt;strong&gt;tất cả số bắt đầu bằng 0839&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^0839.*&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Chặn mọi số bắt đầu bằng &lt;strong&gt;02488&lt;&#x2F;strong&gt; (spam cố định):
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;^2488.*&lt;&#x2F;code&gt; và bật &quot;Ignore Country Code&quot; nếu cần.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;7-luu-y-khi-dung-lau-dai&quot;&gt;7. Lưu ý khi dùng lâu dài&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;Định kỳ mở SpamBlocker xem log chặn để:
&lt;ul&gt;
&lt;li&gt;Bổ sung dải số mới.&lt;&#x2F;li&gt;
&lt;li&gt;Unblock những số lỡ tay chặn nhầm.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Nếu thấy app bỗng không chặn nữa:
&lt;ul&gt;
&lt;li&gt;Kiểm tra lại quyền app.&lt;&#x2F;li&gt;
&lt;li&gt;Tắt tối ưu hóa pin hoặc cho phép chạy nền.&lt;&#x2F;li&gt;
&lt;li&gt;Khởi động lại máy nếu cần.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;&quot;Lý tưởng nhất là kết hợp chặn dải số + chỉ cho phép danh bạ qua, vậy là gần như sạch spam.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;usb-boot&quot;&gt;USB Boot&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;usb-boot-windows-ghi-chu-nhanh&quot;&gt;USB Boot Windows – Ghi chú nhanh&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;1. Copy bộ cài sang USB khác có được không?&lt;&#x2F;strong&gt;
Được. Chỉ cần copy toàn bộ file, không cần nén&#x2F;giải nén.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. USB mới nên dùng định dạng gì?&lt;&#x2F;strong&gt;
Bắt buộc dùng &lt;strong&gt;FAT32&lt;&#x2F;strong&gt; nếu muốn boot UEFI ổn định trên mọi máy.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. Vì sao FAT32?&lt;&#x2F;strong&gt;
UEFI chỉ đọc phân vùng EFI nằm trên FAT32.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. Bộ cài dạng .swm là gì?&lt;&#x2F;strong&gt;
Là file WIM đã được chia nhỏ (&amp;lt;4GB) → chạy tốt trên FAT32.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. Quy trình chuẩn để tạo USB mới:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Format USB → &lt;strong&gt;FAT32, MBR&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Copy toàn bộ file từ USB cũ sang&lt;&#x2F;li&gt;
&lt;li&gt;Xong, boot được trên mọi máy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;6. Khi nào NTFS dùng được?&lt;&#x2F;strong&gt;
Chỉ khi Legacy BIOS hoặc mainboard hỗ trợ NTFS boot → không chắc chắn.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;bluetooth-keyboard&quot;&gt;Bluetooth Keyboard&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;asus-kw100&quot;&gt;ASUS KW100&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251208162704.png&quot; alt=&quot;pasted image 20251208162704&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Con KW100 có &lt;strong&gt;nút Bluetooth&lt;&#x2F;strong&gt; (thường là tổ hợp &lt;code&gt;Fn + 1&#x2F;2&#x2F;3&lt;&#x2F;code&gt; tùy profile).
Mày làm như sau:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Giữ Fn + 1&lt;&#x2F;strong&gt; (hoặc 2, hoặc 3) tầm 3 giây. -&amp;gt; Đèn LED Bluetooth sẽ &lt;strong&gt;nhấp nháy&lt;&#x2F;strong&gt;, nghĩa là vào chế độ pair&lt;&#x2F;li&gt;
&lt;li&gt;Nếu nó yêu cầu nhập mã, thì PC sẽ hiện ra 6 số → mày gõ đúng số đó trên &lt;strong&gt;bàn phím KW100&lt;&#x2F;strong&gt;, rồi nhấn &lt;strong&gt;Enter&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Nếu mày bấm mà nó không nháy → có thể nó đang kết nối profile cũ. Giữ lâu hơn hoặc chuyển sang nút khác.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;logitech-k380&quot;&gt;Logitech K380&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251208162837.png&quot; alt=&quot;pasted image 20251208162837&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-ba-nut-trang-1-2-3-chinh-la-nut-chuyen-thiet-bi&quot;&gt;1. Ba nút trắng 1 – 2 – 3 chính là nút chuyển thiết bị&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Giữ Fn + 1&lt;&#x2F;strong&gt; (hoặc 2, hoặc 3) tầm 3 giây. -&amp;gt; Đèn LED Bluetooth sẽ &lt;strong&gt;nhấp nháy&lt;&#x2F;strong&gt;, nghĩa là vào chế độ pair&lt;&#x2F;li&gt;
&lt;li&gt;Nếu nó yêu cầu nhập mã, thì PC sẽ hiện ra 6 số → mày gõ đúng số đó trên &lt;strong&gt;bàn phím K380&lt;&#x2F;strong&gt;, rồi nhấn &lt;strong&gt;Enter&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Nếu đèn không nháy → mày chỉ nhấn chứ không giữ đủ lâu.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;icon-design&quot;&gt;Icon Design&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;bo-ky-hieu-toi-gian-symbol-system&quot;&gt;Bộ ký hiệu tối giản – Symbol System&lt;&#x2F;h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Mục đích: tạo nhịp thị giác, phân cấp tư duy, đánh dấu logic
Nguyên tắc: ít – chuẩn – sống dai – không màu mè&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;i-core-symbols-loi-he-thong-uu-tien-tuyet-doi&quot;&gt;I. Core Symbols – Lõi hệ thống (ưu tiên tuyệt đối)&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;*&lt;&#x2F;code&gt;  – Asterisk&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;•&lt;&#x2F;code&gt;  – Bullet &#x2F; Dot&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;+&lt;&#x2F;code&gt;  – Plus&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;×&lt;&#x2F;code&gt;  – Cross (nhân)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;·&lt;&#x2F;code&gt;  – Middle Dot&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;#&lt;&#x2F;code&gt;  – Hash&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;—&lt;&#x2F;code&gt;  – Em Dash&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;|&lt;&#x2F;code&gt;  – Vertical Bar&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;°&lt;&#x2F;code&gt;  – Degree &#x2F; Marker&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;○&lt;&#x2F;code&gt; – Circle (outline)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;ii-structural-symbols-phan-cap-cau-truc&quot;&gt;II. Structural Symbols – Phân cấp &amp;amp; cấu trúc&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;◦&lt;&#x2F;code&gt; – Small Circle&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;□&lt;&#x2F;code&gt; – Square (outline)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;■&lt;&#x2F;code&gt; – Square (filled)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;△&lt;&#x2F;code&gt; – Triangle (outline)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;▲&lt;&#x2F;code&gt; – Triangle (filled)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;◇&lt;&#x2F;code&gt; – Diamond (outline)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;◆&lt;&#x2F;code&gt; – Diamond (filled)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;→&lt;&#x2F;code&gt; – Arrow Right&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;↔&lt;&#x2F;code&gt; – Arrow Both&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;∎&lt;&#x2F;code&gt; – End Mark &#x2F; Block&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;iii-auxiliary-symbols-bo-tro-logic-dung-co-chon-loc&quot;&gt;III. Auxiliary Symbols – Bổ trợ logic (dùng có chọn lọc)&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;~&lt;&#x2F;code&gt; – Tilde&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;=&lt;&#x2F;code&gt; – Equal&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;_&lt;&#x2F;code&gt; – Underscore&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;:&lt;&#x2F;code&gt; – Colon&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;…&lt;&#x2F;code&gt; – Ellipsis&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;¶&lt;&#x2F;code&gt; – Pilcrow&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;§&lt;&#x2F;code&gt; – Section&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⊕&lt;&#x2F;code&gt; – Circled Plus&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⊗&lt;&#x2F;code&gt; – Circled Cross&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⋅&lt;&#x2F;code&gt; – Math Dot&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;iv-extended-symbols-mo-rong-co-chieu-sau-chon-loc-ky&quot;&gt;IV. Extended Symbols – Mở rộng có chiều sâu (chọn lọc kỹ)&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;※&lt;&#x2F;code&gt; – Reference Asterisk (nhấn mạnh, chú thích)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;✕&lt;&#x2F;code&gt; – Cross nhẹ (khác ×)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;✔&lt;&#x2F;code&gt; – Check tối giản&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;✖&lt;&#x2F;code&gt; – Reject &#x2F; Deny&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;▢&lt;&#x2F;code&gt; – Square light&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;▣&lt;&#x2F;code&gt; – Square layered&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;◉&lt;&#x2F;code&gt; – Circle focus&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;◎&lt;&#x2F;code&gt; – Circle double&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;◈&lt;&#x2F;code&gt; – Diamond target&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;▸&lt;&#x2F;code&gt; – Pointer Right&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;v-experimental-symbols-chi-dung-khi-hieu-ro-y-nghia&quot;&gt;V. Experimental Symbols – Chỉ dùng khi hiểu rõ ý nghĩa&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;⌁&lt;&#x2F;code&gt; – Wave separator&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⌂&lt;&#x2F;code&gt; – Home symbol&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⌘&lt;&#x2F;code&gt; – Command&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⌥&lt;&#x2F;code&gt; – Option&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⌗&lt;&#x2F;code&gt; – Sharp logic marker&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;∘&lt;&#x2F;code&gt; – Small math circle&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⊙&lt;&#x2F;code&gt; – Centered dot&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;⊥&lt;&#x2F;code&gt; – Perpendicular &#x2F; Break&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;∴&lt;&#x2F;code&gt; – Therefore&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;∵&lt;&#x2F;code&gt; – Because&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;khac&quot;&gt;Khác&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;list.svg&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;paypal&quot;&gt;PayPal&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;cach-1-su-dung-paypal-me&quot;&gt;Cách 1: Sử dụng paypal.me&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;paypal.me&#x2F;nguyendinhquoc&quot;&gt;https:&#x2F;&#x2F;paypal.me&#x2F;nguyendinhquoc&lt;&#x2F;a&gt;
hoặc đặt mặc định là 5$: &lt;a href=&quot;https:&#x2F;&#x2F;paypal.me&#x2F;nguyendinhquoc&#x2F;5&quot;&gt;https:&#x2F;&#x2F;paypal.me&#x2F;nguyendinhquoc&#x2F;5&lt;&#x2F;a&gt;
Note: Thêm param amount &lt;code&gt;&#x2F;5&lt;&#x2F;code&gt; để đặt mặc định số tiền, hoặc thêm &lt;code&gt;?locale.x=vi_VN&lt;&#x2F;code&gt; để cố định ngôn ngữ.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cach-2-paypal-smart-buttons-muon-ux-tot&quot;&gt;Cách 2: PayPal Smart Buttons (muốn UX tốt)&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;buoc-lay-client-id&quot;&gt;Bước lấy Client ID&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;Vào &lt;a href=&quot;https:&#x2F;&#x2F;developer.paypal.com&quot;&gt;https:&#x2F;&#x2F;developer.paypal.com&lt;&#x2F;a&gt; → Dashboard → Apps &amp;amp; Credentials → Tạo app mới → Copy &lt;strong&gt;Client ID&lt;&#x2F;strong&gt; (live khi đã sẵn sàng, sandbox để test).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251027165004.png&quot; alt=&quot;pasted image 20251027165004&quot; &#x2F;&gt;
&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251027165308.png&quot; alt=&quot;pasted image 20251027165308&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;imported&#x2F;2026-07-18-other-tools&#x2F;pasted-image-20251027165235.png&quot; alt=&quot;pasted image 20251027165235&quot; &#x2F;&gt;
Client ID: AeP5pRvHAaGRuYEzMfFF0miT3LsxlmtTUYuQQBB1sgt3aXhmdpSnOd0SAdEa7jlxloZGkyJlyKO5mF4m
Secret key 1: EILh6rrhQ6ei2OgCR6L-hXY72RuQnd3DIpQxImvhNSZYRf1FC4AEUi0rctY9QitAueykfizBylLJMc23&lt;&#x2F;p&gt;
&lt;h4 id=&quot;vi-du-implement-trong-src-pages-donate-astro&quot;&gt;Ví dụ implement trong &lt;code&gt;src&#x2F;pages&#x2F;donate.astro&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;pre&gt;&lt;code&gt;---
&amp;#x2F;&amp;#x2F; src&amp;#x2F;pages&amp;#x2F;donate.astro
const PAYPAL_CLIENT_ID = &amp;quot;REPLACE_WITH_YOUR_CLIENT_ID&amp;quot;;
---
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;utf-8&amp;quot; &amp;#x2F;&amp;gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width,initial-scale=1&amp;quot; &amp;#x2F;&amp;gt;
    &amp;lt;title&amp;gt;Donate&amp;lt;&amp;#x2F;title&amp;gt;
  &amp;lt;&amp;#x2F;head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;main style=&amp;quot;max-width:700px;margin:40px auto;text-align:center;&amp;quot;&amp;gt;
      &amp;lt;h1&amp;gt;Ủng hộ tác giả&amp;lt;&amp;#x2F;h1&amp;gt;
      &amp;lt;p&amp;gt;Chọn số tiền và phương thức để ủng hộ.&amp;lt;&amp;#x2F;p&amp;gt;

      &amp;lt;!-- Option: preset amounts --&amp;gt;
      &amp;lt;div id=&amp;quot;amounts&amp;quot; style=&amp;quot;margin:20px 0;&amp;quot;&amp;gt;
        &amp;lt;button data-amount=&amp;quot;5&amp;quot;&amp;gt;5 USD&amp;lt;&amp;#x2F;button&amp;gt;
        &amp;lt;button data-amount=&amp;quot;10&amp;quot;&amp;gt;10 USD&amp;lt;&amp;#x2F;button&amp;gt;
        &amp;lt;button data-amount=&amp;quot;25&amp;quot;&amp;gt;25 USD&amp;lt;&amp;#x2F;button&amp;gt;
        &amp;lt;button data-amount=&amp;quot;50&amp;quot;&amp;gt;50 USD&amp;lt;&amp;#x2F;button&amp;gt;
      &amp;lt;&amp;#x2F;div&amp;gt;

      &amp;lt;!-- PayPal button container --&amp;gt;
      &amp;lt;div id=&amp;quot;paypal-button-container&amp;quot;&amp;gt;&amp;lt;&amp;#x2F;div&amp;gt;

      &amp;lt;p id=&amp;quot;status&amp;quot; style=&amp;quot;margin-top:20px;&amp;quot;&amp;gt;&amp;lt;&amp;#x2F;p&amp;gt;
    &amp;lt;&amp;#x2F;main&amp;gt;

    &amp;lt;!-- PayPal SDK --&amp;gt;
    &amp;lt;script src={`https:&amp;#x2F;&amp;#x2F;www.paypal.com&amp;#x2F;sdk&amp;#x2F;js?client-id=${PAYPAL_CLIENT_ID}&amp;amp;currency=USD`}&amp;gt;&amp;lt;&amp;#x2F;script&amp;gt;

    &amp;lt;script&amp;gt;
      (function(){
        &amp;#x2F;&amp;#x2F; default amount
        let currentAmount = &amp;quot;5.00&amp;quot;;

        &amp;#x2F;&amp;#x2F; amount buttons
        document.querySelectorAll(&amp;#x27;#amounts button&amp;#x27;).forEach(btn=&amp;gt;{
          btn.addEventListener(&amp;#x27;click&amp;#x27;, ()=&amp;gt; {
            currentAmount = parseFloat(btn.dataset.amount).toFixed(2);
            document.getElementById(&amp;#x27;status&amp;#x27;).textContent = &amp;quot;Số tiền: $&amp;quot; + currentAmount;
          });
        });

        &amp;#x2F;&amp;#x2F; render paypal button
        paypal.Buttons({
          style: { layout: &amp;#x27;vertical&amp;#x27;, color: &amp;#x27;gold&amp;#x27;, shape: &amp;#x27;rect&amp;#x27;, label: &amp;#x27;donate&amp;#x27; },

          createOrder: function(data, actions) {
            return actions.order.create({
              purchase_units: [{
                amount: {
                  value: currentAmount
                },
                description: &amp;quot;Ủng hộ Quoc - Donate&amp;quot;
              }]
            });
          },

          onApprove: function(data, actions) {
            return actions.order.capture().then(function(details) {
              document.getElementById(&amp;#x27;status&amp;#x27;).textContent = &amp;quot;Cảm ơn &amp;quot; + details.payer.name.given_name + &amp;quot;! Giao dịch id: &amp;quot; + data.orderID;
              &amp;#x2F;&amp;#x2F; TODO: gửi thông tin về server nếu cần lưu lại
            });
          },

          onError: function(err) {
            console.error(err);
            document.getElementById(&amp;#x27;status&amp;#x27;).textContent = &amp;quot;Có lỗi khi xử lý thanh toán.&amp;quot;;
          }
        }).render(&amp;#x27;#paypal-button-container&amp;#x27;);

      })();
    &amp;lt;&amp;#x2F;script&amp;gt;
  &amp;lt;&amp;#x2F;body&amp;gt;
&amp;lt;&amp;#x2F;html&amp;gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Ghi chú:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Thay &lt;code&gt;REPLACE_WITH_YOUR_CLIENT_ID&lt;&#x2F;code&gt; bằng Client ID thật.&lt;&#x2F;li&gt;
&lt;li&gt;Đổi &lt;code&gt;currency=USD&lt;&#x2F;code&gt; sang VNĐ hay EUR nếu cần (PayPal hỗ trợ nhiều loại tiền).&lt;&#x2F;li&gt;
&lt;li&gt;Nếu muốn &lt;strong&gt;test&lt;&#x2F;strong&gt;, dùng sandbox Client ID và sandbox account trong PayPal dev. Khi chuyển sang production đổi client-id.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Demo</title>
        <published>2026-07-17T00:00:00+00:00</published>
        <updated>2026-07-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/demo/"/>
        <id>https://quoc.app/write/demo/</id>
        
        <content type="html" xml:base="https://quoc.app/write/demo/">&lt;div lang=&quot;en&quot;&gt;
&lt;p&gt;Demo $1000 · 2% risk · Trend-following&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tong-quan&quot;&gt;Tổng quan&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;equity-curve.png&quot; alt=&quot;Đường vốn&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Lệnh: &lt;strong&gt;214&#x2F;100&lt;&#x2F;strong&gt; (214 đã đóng, 0 đang mở, 0 đang chờ)&lt;&#x2F;li&gt;
&lt;li&gt;Đã đóng: &lt;strong&gt;30 thắng (14%)&lt;&#x2F;strong&gt;, 180 thua, 4 hòa, lãi&#x2F;lỗ: &lt;strong&gt;$-583.4&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Tỷ lệ lãi&#x2F;lỗ: &lt;strong&gt;4.85&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lãi&#x2F;lỗ ròng: $-583.4 (-29.2R)&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;thong-ke&quot;&gt;Thống kê&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Kỳ vọng: &lt;strong&gt;$-2.73&lt;&#x2F;strong&gt; mỗi lệnh (-0.14R)&lt;&#x2F;li&gt;
&lt;li&gt;Kết quả trung bình: &lt;strong&gt;-0.14R&lt;&#x2F;strong&gt; mỗi lệnh&lt;&#x2F;li&gt;
&lt;li&gt;Trung vị thắng&#x2F;thua: &lt;strong&gt;$67.72&lt;&#x2F;strong&gt; &#x2F; &lt;strong&gt;$-20.38&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Drawdown tối đa: &lt;strong&gt;$1452.62&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Cơ sở R: $20.0 (2.0% của $1000.0)&lt;&#x2F;li&gt;
&lt;li&gt;Chuỗi hiện tại: &lt;strong&gt;thắng x1&lt;&#x2F;strong&gt; ($+164.41)&lt;&#x2F;li&gt;
&lt;li&gt;Chuỗi thua dài nhất: &lt;strong&gt;30&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;hoat-dong-giao-dich-2026&quot;&gt;Hoạt động giao dịch 2026&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;trading-heatmap-2026.png&quot; alt=&quot;Biểu đồ hoạt động&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;trades-per-month.png&quot; alt=&quot;Lệnh theo tháng&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;pl-by-symbol.png&quot; alt=&quot;Lãi&#x2F;lỗ theo cặp&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lenh-da-dong&quot;&gt;LỆNH ĐÃ ĐÓNG&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;theo-cap&quot;&gt;Theo cặp&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Cặp&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Tỷ lệ thắng&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;XAUUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;128&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;14%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$43.04&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;UKOILm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-19.08&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;AUDJPYm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-20.5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;USTECm&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-39.09&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;US500_x100m&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-41.95&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;US500m&lt;&#x2F;td&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;25%&lt;&#x2F;td&gt;&lt;td&gt;$-60.81&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GBPUSDm&lt;&#x2F;td&gt;&lt;td&gt;13&lt;&#x2F;td&gt;&lt;td&gt;15%&lt;&#x2F;td&gt;&lt;td&gt;$-105.39&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;EURUSDm&lt;&#x2F;td&gt;&lt;td&gt;41&lt;&#x2F;td&gt;&lt;td&gt;17%&lt;&#x2F;td&gt;&lt;td&gt;$-121.61&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;22&lt;&#x2F;td&gt;&lt;td&gt;9%&lt;&#x2F;td&gt;&lt;td&gt;$-218.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;theo-thang&quot;&gt;Theo tháng&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tháng&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Thắng&lt;&#x2F;th&gt;&lt;th&gt;Thua&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-07&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;9&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;7&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;22%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$168.06&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-06&lt;&#x2F;td&gt;&lt;td&gt;46&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;41&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-353.87&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-05&lt;&#x2F;td&gt;&lt;td&gt;34&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;31&lt;&#x2F;td&gt;&lt;td&gt;6%&lt;&#x2F;td&gt;&lt;td&gt;$-232.98&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-04&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;39&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;7&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;30&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;18%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$23.27&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-03&lt;&#x2F;td&gt;&lt;td&gt;26&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;24&lt;&#x2F;td&gt;&lt;td&gt;8%&lt;&#x2F;td&gt;&lt;td&gt;$-224.27&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-02&lt;&#x2F;td&gt;&lt;td&gt;21&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;17&lt;&#x2F;td&gt;&lt;td&gt;14%&lt;&#x2F;td&gt;&lt;td&gt;$-191.14&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-01&lt;&#x2F;td&gt;&lt;td&gt;18&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;16&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-279.95&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2025-12&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;19&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;6&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;13&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;32%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$509.88&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-11&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;50%&lt;&#x2F;td&gt;&lt;td&gt;$-2.4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;cap-theo-thang&quot;&gt;Cặp theo tháng&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tháng&lt;&#x2F;th&gt;&lt;th&gt;Cặp&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-07&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;XAUUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;9&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;22%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$168.06&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-06&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;BTCUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;50%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$29.77&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-06&lt;&#x2F;td&gt;&lt;td&gt;AUDJPYm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-20.5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-06&lt;&#x2F;td&gt;&lt;td&gt;GBPUSDm&lt;&#x2F;td&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;14%&lt;&#x2F;td&gt;&lt;td&gt;$-38.19&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-06&lt;&#x2F;td&gt;&lt;td&gt;EURUSDm&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-111.11&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-06&lt;&#x2F;td&gt;&lt;td&gt;XAUUSDm&lt;&#x2F;td&gt;&lt;td&gt;31&lt;&#x2F;td&gt;&lt;td&gt;10%&lt;&#x2F;td&gt;&lt;td&gt;$-213.84&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-05&lt;&#x2F;td&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;8&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-106.75&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-05&lt;&#x2F;td&gt;&lt;td&gt;XAUUSDm&lt;&#x2F;td&gt;&lt;td&gt;26&lt;&#x2F;td&gt;&lt;td&gt;8%&lt;&#x2F;td&gt;&lt;td&gt;$-126.23&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-04&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;XAUUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;30&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;20%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$117.62&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-04&lt;&#x2F;td&gt;&lt;td&gt;GBPUSDm&lt;&#x2F;td&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;25%&lt;&#x2F;td&gt;&lt;td&gt;$-27.06&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-04&lt;&#x2F;td&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-67.29&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2026-03&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;XAUUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;9&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;11%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$20.55&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-03&lt;&#x2F;td&gt;&lt;td&gt;GBPUSDm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-21.0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-03&lt;&#x2F;td&gt;&lt;td&gt;US500_x100m&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-41.95&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-03&lt;&#x2F;td&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-59.95&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-03&lt;&#x2F;td&gt;&lt;td&gt;EURUSDm&lt;&#x2F;td&gt;&lt;td&gt;11&lt;&#x2F;td&gt;&lt;td&gt;9%&lt;&#x2F;td&gt;&lt;td&gt;$-121.92&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-02&lt;&#x2F;td&gt;&lt;td&gt;EURUSDm&lt;&#x2F;td&gt;&lt;td&gt;12&lt;&#x2F;td&gt;&lt;td&gt;17%&lt;&#x2F;td&gt;&lt;td&gt;$-48.36&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-02&lt;&#x2F;td&gt;&lt;td&gt;XAUUSDm&lt;&#x2F;td&gt;&lt;td&gt;9&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-142.78&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-01&lt;&#x2F;td&gt;&lt;td&gt;GBPUSDm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-19.14&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-01&lt;&#x2F;td&gt;&lt;td&gt;USTECm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-19.66&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-01&lt;&#x2F;td&gt;&lt;td&gt;EURUSDm&lt;&#x2F;td&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;14%&lt;&#x2F;td&gt;&lt;td&gt;$-66.29&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2026-01&lt;&#x2F;td&gt;&lt;td&gt;XAUUSDm&lt;&#x2F;td&gt;&lt;td&gt;9&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-174.86&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2025-12&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;XAUUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;5&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;40%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$394.52&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2025-12&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;EURUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;5&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;40%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$217.6&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-12&lt;&#x2F;td&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;33%&lt;&#x2F;td&gt;&lt;td&gt;$-2.92&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-12&lt;&#x2F;td&gt;&lt;td&gt;UKOILm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-19.08&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-12&lt;&#x2F;td&gt;&lt;td&gt;USTECm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-19.43&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-12&lt;&#x2F;td&gt;&lt;td&gt;US500m&lt;&#x2F;td&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;25%&lt;&#x2F;td&gt;&lt;td&gt;$-60.81&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2025-11&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;EURUSDm&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;100%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$8.47&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2025-11&lt;&#x2F;td&gt;&lt;td&gt;BTCUSDm&lt;&#x2F;td&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-10.87&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;hold-time-vs-pl.png&quot; alt=&quot;Thời gian giữ vs lãi&#x2F;lỗ&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;phan-tich-thoi-gian-giu-lenh&quot;&gt;Phân tích thời gian giữ lệnh&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Khoảng thời gian&lt;&#x2F;th&gt;&lt;th&gt;Ngày&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Tỷ lệ thắng&lt;&#x2F;th&gt;&lt;th&gt;Tổng lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;th&gt;TB lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0-100h&lt;&#x2F;td&gt;&lt;td&gt;0-4d&lt;&#x2F;td&gt;&lt;td&gt;206&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-1669.66&lt;&#x2F;td&gt;&lt;td&gt;$-8.11&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;100-200h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;4-8d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;4&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;75%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$352.88&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$88.22&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;200-300h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;8-12d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;100%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$290.44&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$145.22&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;300-400h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;12-16d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;100%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$276.84&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$276.84&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;400-500h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;16-20d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;100%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$166.10&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$166.10&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;phan-tich-xauusdm&quot;&gt;&lt;span style=&quot;color:#3b82f6&quot;&gt;PHÂN TÍCH: XAUUSDm&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;buy-vs-sell&quot;&gt;Buy vs Sell&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Hướng&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Thắng&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;Buy&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;72&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;8&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;11%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$29.53&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;Sell&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;56&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;10&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;18%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$13.51&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;session-gio-mo-lenh&quot;&gt;Session (giờ mở lệnh)&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Session&lt;&#x2F;th&gt;&lt;th&gt;Giờ&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Thắng&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Asian&lt;&#x2F;td&gt;&lt;td&gt;0-8h&lt;&#x2F;td&gt;&lt;td&gt;44&lt;&#x2F;td&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-250.95&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;London&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;8-14h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;27&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;5&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;19%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$166.63&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;NY&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;14-21h&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;51&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;8&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;16%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$251.68&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Late&lt;&#x2F;td&gt;&lt;td&gt;21-0h&lt;&#x2F;td&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-124.32&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;thoi-gian-giu-lenh&quot;&gt;Thời gian giữ lệnh&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;trading&#x2F;hold-time-vs-pl-xauusdm.png&quot; alt=&quot;Hold time: XAUUSDm&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Khoảng&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Tổng P&#x2F;L&lt;&#x2F;th&gt;&lt;th&gt;TB P&#x2F;L&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0-1h&lt;&#x2F;td&gt;&lt;td&gt;77&lt;&#x2F;td&gt;&lt;td&gt;10%&lt;&#x2F;td&gt;&lt;td&gt;$-680.63&lt;&#x2F;td&gt;&lt;td&gt;$-8.84&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;1-4h&lt;&#x2F;td&gt;&lt;td&gt;19&lt;&#x2F;td&gt;&lt;td&gt;11%&lt;&#x2F;td&gt;&lt;td&gt;$-195.82&lt;&#x2F;td&gt;&lt;td&gt;$-10.31&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;4-12h&lt;&#x2F;td&gt;&lt;td&gt;14&lt;&#x2F;td&gt;&lt;td&gt;7%&lt;&#x2F;td&gt;&lt;td&gt;$-132.15&lt;&#x2F;td&gt;&lt;td&gt;$-9.44&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;12-24h&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-42.89&lt;&#x2F;td&gt;&lt;td&gt;$-14.30&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;1-2d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;6&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;33%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$318.49&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$53.08&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;2-4d&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;5&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;40%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$113.56&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$22.71&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;4d+&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;4&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;75%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$662.48&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$165.62&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;khoi-luong-lot&quot;&gt;Khối lượng (Lot)&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Lot&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;th&gt;Win%&lt;&#x2F;th&gt;&lt;th&gt;Lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;th&gt;TB lãi&#x2F;lỗ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0.01&lt;&#x2F;td&gt;&lt;td&gt;91&lt;&#x2F;td&gt;&lt;td&gt;13%&lt;&#x2F;td&gt;&lt;td&gt;$-140.11&lt;&#x2F;td&gt;&lt;td&gt;$-1.54&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;0.02&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;33&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;18%&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$248.87&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;span style=&quot;display:block;background:#f4f4f4;padding:3px 10px;margin:-3px -10px&quot;&gt;&lt;strong&gt;+$7.54&lt;&#x2F;strong&gt;&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;0.03&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-41.45&lt;&#x2F;td&gt;&lt;td&gt;$-20.73&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;0.06&lt;&#x2F;td&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;0%&lt;&#x2F;td&gt;&lt;td&gt;$-24.27&lt;&#x2F;td&gt;&lt;td&gt;$-12.13&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;chuoi-lien-tiep&quot;&gt;Chuỗi liên tiếp&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Chuỗi thắng dài nhất: &lt;strong&gt;2&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Chuỗi thua dài nhất: &lt;strong&gt;22&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;risk-reward&quot;&gt;Risk&#x2F;Reward&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;TB thắng: &lt;strong&gt;$95.6&lt;&#x2F;strong&gt; | TB thua: &lt;strong&gt;$-15.68&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Trung vị thắng: &lt;strong&gt;$102.27&lt;&#x2F;strong&gt; | Trung vị thua: &lt;strong&gt;$-20.14&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;R:R riêng: &lt;strong&gt;6.1&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>OpenSpec</title>
        <published>2026-04-29T00:00:00+00:00</published>
        <updated>2026-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/share/openspec/"/>
        <id>https://quoc.app/share/openspec/</id>
        
        <content type="html" xml:base="https://quoc.app/share/openspec/">&lt;h2 id=&quot;openspec-la-gi&quot;&gt;OpenSpec là gì?&lt;&#x2F;h2&gt;
&lt;p&gt;OpenSpec đồng bộ con người và trợ lý lập trình AI thông qua &lt;strong&gt;phát triển dựa trên đặc tả (spec-driven development)&lt;&#x2F;strong&gt;, giúp hai bên thống nhất &lt;strong&gt;cái cần xây dựng&lt;&#x2F;strong&gt; trước khi viết bất kỳ dòng code nào. &lt;strong&gt;Không cần API key&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tai-sao-can-openspec&quot;&gt;Tại sao cần OpenSpec?&lt;&#x2F;h2&gt;
&lt;p&gt;Trợ lý lập trình AI rất mạnh, nhưng &lt;strong&gt;khó đoán&lt;&#x2F;strong&gt; khi yêu cầu nằm rải rác trong lịch sử chat. OpenSpec bổ sung một &lt;strong&gt;luồng làm việc đặc tả nhẹ nhàng&lt;&#x2F;strong&gt;, khóa chặt ý định trước khi triển khai, từ đó tạo ra kết quả &lt;strong&gt;xác định được và có thể kiểm duyệt&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ket-qua-chinh&quot;&gt;Kết quả chính:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Các bên (con người và AI) &lt;strong&gt;thống nhất đặc tả trước khi bắt đầu&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Thư mục thay đổi có cấu trúc (&lt;code&gt;proposals&lt;&#x2F;code&gt;, &lt;code&gt;tasks&lt;&#x2F;code&gt;, &lt;code&gt;spec updates&lt;&#x2F;code&gt;) giúp &lt;strong&gt;phạm vi rõ ràng và có thể kiểm tra&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Minh bạch&lt;&#x2F;strong&gt; về những gì đang được đề xuất, đang thực hiện, hay đã lưu trữ.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tương thích với các công cụ AI mày đang dùng&lt;&#x2F;strong&gt;: lệnh gạch chéo (&lt;code&gt;&#x2F;&lt;&#x2F;code&gt;) nếu hỗ trợ, hoặc quy tắc ngữ cảnh ở mọi nơi khác.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;so-sanh-openspec-tong-quan&quot;&gt;So sánh OpenSpec (tổng quan)&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nhẹ nhàng&lt;&#x2F;strong&gt;: luồng làm việc đơn giản, không cần API key, thiết lập tối thiểu.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ưu tiên dự án hiện có (brownfield-first)&lt;&#x2F;strong&gt;: hoạt động tốt không chỉ cho tính năng mới (0→1). OpenSpec tách biệt &lt;strong&gt;nguồn sự thật hiện tại&lt;&#x2F;strong&gt; và &lt;strong&gt;đề xuất thay đổi&lt;&#x2F;strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openspec&#x2F;specs&#x2F;&lt;&#x2F;code&gt;: đặc tả hiện tại (nguồn sự thật)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;openspec&#x2F;changes&#x2F;&lt;&#x2F;code&gt;: đề xuất cập nhật
→ Giúp &lt;strong&gt;diff rõ ràng&lt;&#x2F;strong&gt;, dễ quản lý khi thay đổi trải dài nhiều đặc tả.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Theo dõi thay đổi&lt;&#x2F;strong&gt;: đề xuất, nhiệm vụ và delta đặc tả được lưu cùng nhau; khi lưu trữ, các cập nhật được hợp nhất ngược vào đặc tả gốc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So với &lt;strong&gt;spec-kit&lt;&#x2F;strong&gt; và &lt;strong&gt;Kiro&lt;&#x2F;strong&gt;: chúng mạnh khi làm tính năng hoàn toàn mới (0→1). OpenSpec còn &lt;strong&gt;vượt trội khi sửa đổi hành vi hiện có (1→n)&lt;&#x2F;strong&gt;, đặc biệt khi cập nhật liên quan đến nhiều đặc tả.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;cach-hoat-dong&quot;&gt;Cách hoạt động&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;┌────────────────────┐
│ Soạn thảo đề xuất  │
│ thay đổi           │
└────────┬───────────┘
         │ chia sẻ ý định với AI
         ▼
┌────────────────────┐
│ Xem xét &amp;amp; Thống    │
│ nhất (sửa đặc tả&amp;#x2F;  │◀──── vòng lặp phản hồi ──────┐
│ nhiệm vụ)          │                              │
└────────┬───────────┘                              │
         │ kế hoạch được phê duyệt                  │
         ▼                                          │
┌────────────────────┐                              │
│ Triển khai nhiệm   │───────────────────────────────┘
│ vụ (AI viết code)  │
└────────┬───────────┘
         │ triển khai thay đổi
         ▼
┌────────────────────┐
│ Lưu trữ &amp;amp; Cập nhật │
│ Đặc tả (nguồn)     │
└────────────────────┘
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Soạn thảo đề xuất thay đổi&lt;&#x2F;strong&gt; mô tả những cập nhật đặc tả mày muốn.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Xem xét đề xuất&lt;&#x2F;strong&gt; cùng trợ lý AI cho đến khi mọi người đồng ý.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Triển khai các nhiệm vụ&lt;&#x2F;strong&gt; tham chiếu đến đặc tả đã thống nhất.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lưu trữ thay đổi&lt;&#x2F;strong&gt; để hợp nhất các cập nhật đã được phê duyệt vào đặc tả gốc.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;bat-dau&quot;&gt;Bắt đầu&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;cac-cong-cu-ai-duoc-ho-tro&quot;&gt;Các công cụ AI được hỗ trợ&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;lenh-gach-cheo-tich-hop-san&quot;&gt;Lệnh gạch chéo tích hợp sẵn&lt;&#x2F;h4&gt;
&lt;p&gt;Các công cụ này có lệnh OpenSpec tích hợp. Chọn tích hợp OpenSpec khi được nhắc.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Công cụ&lt;&#x2F;th&gt;&lt;th&gt;Lệnh&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Claude Code&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec:proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec:apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec:archive&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;CodeBuddy Code (CLI)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec:proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec:apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec:archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.codebuddy&#x2F;commands&#x2F;&lt;&#x2F;code&gt;) — xem tài liệu&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cursor&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Cline&lt;&#x2F;td&gt;&lt;td&gt;Quy tắc trong thư mục &lt;code&gt;.clinerules&#x2F;&lt;&#x2F;code&gt; (&lt;code&gt;.clinerules&#x2F;openspec-*.md&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Factory Droid&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.factory&#x2F;commands&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;OpenCode&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kilo Code&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal.md&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply.md&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive.md&lt;&#x2F;code&gt; (trong &lt;code&gt;.kilocode&#x2F;workflows&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Windsurf&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.windsurf&#x2F;workflows&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Codex&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt; (toàn cục: &lt;code&gt;~&#x2F;.codex&#x2F;prompts&lt;&#x2F;code&gt;, cài tự động)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;GitHub Copilot&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.github&#x2F;prompts&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Amazon Q Developer&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;@openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;@openspec-apply&lt;&#x2F;code&gt;, &lt;code&gt;@openspec-archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.amazonq&#x2F;prompts&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Auggie (Augment CLI)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;openspec-proposal&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec:apply&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-archive&lt;&#x2F;code&gt; (trong &lt;code&gt;.augment&#x2F;commands&#x2F;&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Kilo Code&lt;&#x2F;strong&gt; tự động phát hiện luồng làm việc nhóm. Lưu các file được tạo vào &lt;code&gt;.kilocode&#x2F;workflows&#x2F;&lt;&#x2F;code&gt; và kích hoạt từ bảng lệnh bằng &lt;code&gt;&#x2F;openspec-proposal.md&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;openspec-apply.md&lt;&#x2F;code&gt;, hoặc &lt;code&gt;&#x2F;openspec-archive.md&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;tuong-thich-voi-agents-md&quot;&gt;Tương thích với &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Các công cụ này tự động đọc hướng dẫn luồng làm việc từ &lt;code&gt;openspec&#x2F;AGENTS.md&lt;&#x2F;code&gt;. Yêu cầu chúng tuân theo luồng OpenSpec nếu cần nhắc lại. Tìm hiểu thêm về &lt;a href=&quot;https:&#x2F;&#x2F;agents.md&#x2F;&quot;&gt;quy ước AGENTS.md&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Công cụ&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Amp • Jules • Gemini CLI • Các công cụ khác&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h3 id=&quot;cai-dat-khoi-tao&quot;&gt;Cài đặt &amp;amp; Khởi tạo&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;yeu-cau-truoc&quot;&gt;Yêu cầu trước&lt;&#x2F;h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Node.js &amp;gt;= 20.19.0&lt;&#x2F;strong&gt; — Kiểm tra phiên bản bằng lệnh: &lt;code&gt;node --version&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;buoc-1-cai-cli-toan-cuc&quot;&gt;Bước 1: Cài CLI toàn cục&lt;&#x2F;h4&gt;
&lt;pre&gt;&lt;code&gt;npm install -g @fission-ai&amp;#x2F;openspec@latest
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Xác minh cài đặt:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;openspec --version
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;buoc-2-khoi-tao-openspec-trong-du-an&quot;&gt;Bước 2: Khởi tạo OpenSpec trong dự án&lt;&#x2F;h4&gt;
&lt;p&gt;Chuyển đến thư mục dự án:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;cd my-project
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Chạy lệnh khởi tạo:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;	openspec init
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Điều gì xảy ra khi khởi tạo:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Mày sẽ được hỏi chọn các công cụ AI được hỗ trợ tích hợp sẵn (Claude Code, CodeBuddy, Cursor, OpenCode, v.v.); các trợ lý khác luôn dựa vào stub &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; chung.&lt;&#x2F;li&gt;
&lt;li&gt;OpenSpec tự động cấu hình lệnh gạch chéo cho các công cụ mày chọn và luôn tạo file &lt;code&gt;AGENTS.md&lt;&#x2F;code&gt; được quản lý tại gốc dự án.&lt;&#x2F;li&gt;
&lt;li&gt;Một cấu trúc thư mục &lt;code&gt;openspec&#x2F;&lt;&#x2F;code&gt; mới được tạo trong dự án.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Sau khi thiết lập:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Các công cụ AI chính có thể kích hoạt luồng &lt;code&gt;&#x2F;openspec&lt;&#x2F;code&gt; mà &lt;strong&gt;không cần cấu hình thêm&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Chạy &lt;code&gt;openspec list&lt;&#x2F;code&gt; để xác minh thiết lập và xem các thay đổi đang hoạt động.&lt;&#x2F;li&gt;
&lt;li&gt;Nếu trợ lý lập trình &lt;strong&gt;chưa hiển thị lệnh gạch chéo ngay&lt;&#x2F;strong&gt;, hãy khởi động lại nó. Lệnh gạch chéo được tải khi khởi động, nên khởi động lại đảm bảo chúng xuất hiện.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;so-sanh-openspec&quot;&gt;So sánh OpenSpec&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;so-voi-spec-kit&quot;&gt;So với spec-kit&lt;&#x2F;h3&gt;
&lt;p&gt;Mô hình hai thư mục của OpenSpec (&lt;code&gt;openspec&#x2F;specs&#x2F;&lt;&#x2F;code&gt; cho sự thật hiện tại, &lt;code&gt;openspec&#x2F;changes&#x2F;&lt;&#x2F;code&gt; cho đề xuất) &lt;strong&gt;tách biệt trạng thái và diff&lt;&#x2F;strong&gt;, giúp mở rộng khi sửa đổi tính năng hiện có hoặc chạm vào nhiều đặc tả. spec-kit mạnh cho dự án mới (0→1) nhưng ít cấu trúc hơn cho cập nhật chéo đặc tả và tính năng phát triển.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-voi-kiro-dev&quot;&gt;So với Kiro.dev&lt;&#x2F;h3&gt;
&lt;p&gt;OpenSpec gom mọi thay đổi cho một tính năng vào &lt;strong&gt;một thư mục duy nhất&lt;&#x2F;strong&gt; (&lt;code&gt;openspec&#x2F;changes&#x2F;tên-tính-năng&#x2F;&lt;&#x2F;code&gt;), giúp dễ theo dõi đặc tả, nhiệm vụ và thiết kế liên quan. Kiro phân tán cập nhật vào nhiều thư mục đặc tả, khiến việc theo dõi tính năng trở nên khó khăn hơn.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-voi-khong-dung-dac-ta&quot;&gt;So với Không dùng đặc tả&lt;&#x2F;h3&gt;
&lt;p&gt;Không có đặc tả, trợ lý AI tạo code từ các yêu cầu mơ hồ, thường &lt;strong&gt;thiếu yêu cầu&lt;&#x2F;strong&gt; hoặc &lt;strong&gt;thêm tính năng không mong muốn&lt;&#x2F;strong&gt;. OpenSpec mang lại &lt;strong&gt;khả năng dự đoán&lt;&#x2F;strong&gt; bằng cách thống nhất hành vi mong muốn &lt;strong&gt;trước khi viết code&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;cac-lenh-thuong-dung&quot;&gt;Các lệnh thường dùng&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;openspec list               # Xem các thư mục thay đổi đang hoạt động
openspec view               # Bảng điều khiển tương tác về đặc tả và thay đổi
openspec show &amp;lt;change&amp;gt;      # Hiển thị chi tiết thay đổi (đề xuất, nhiệm vụ, cập nhật đặc tả)
openspec validate &amp;lt;change&amp;gt;  # Kiểm tra định dạng và cấu trúc đặc tả
openspec archive &amp;lt;change&amp;gt; [--yes|-y]   # Chuyển thay đổi đã hoàn thành vào thư mục lưu trữ (không hỏi lại nếu dùng --yes)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;dinh-dang-delta&quot;&gt;Định dạng Delta&lt;&#x2F;h2&gt;
&lt;p&gt;Delta là &quot;bản vá&quot; cho thấy đặc tả thay đổi thế nào:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;## YÊU CẦU ĐƯỢC THÊM&lt;&#x2F;code&gt;: Tính năng mới&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;## YÊU CẦU ĐƯỢC SỬA&lt;&#x2F;code&gt;: Hành vi thay đổi (phải bao gồm toàn bộ văn bản đã cập nhật)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;## YÊU CẦU BỊ XÓA&lt;&#x2F;code&gt;: Tính năng đã ngừng dùng&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Yêu cầu định dạng:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Dùng &lt;code&gt;### Yêu cầu: &amp;lt;tên&amp;gt;&lt;&#x2F;code&gt; cho tiêu đề&lt;&#x2F;li&gt;
&lt;li&gt;Mỗi yêu cầu phải có ít nhất một khối &lt;code&gt;#### Kịch bản:&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Dùng &lt;strong&gt;PHẢI&lt;&#x2F;strong&gt; hoặc &lt;strong&gt;BẮT BUỘC&lt;&#x2F;strong&gt; trong nội dung yêu cầu&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;vi-du-ai-tao-file-openspec-nhu-the-nao&quot;&gt;Ví dụ: AI tạo file OpenSpec như thế nào&lt;&#x2F;h2&gt;
&lt;p&gt;Khi mày yêu cầu trợ lý AI &quot;thêm xác thực hai yếu tố&quot;, nó tạo:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;openspec&amp;#x2F;
├── specs&amp;#x2F;
│   └── auth&amp;#x2F;
│       └── spec.md           # Đặc tả xác thực hiện tại (nếu tồn tại)
└── changes&amp;#x2F;
    └── add-2fa&amp;#x2F;              # AI tạo toàn bộ cấu trúc này
        ├── proposal.md       # Lý do và nội dung thay đổi
        ├── tasks.md          # Danh sách kiểm tra triển khai
        ├── design.md         # Quyết định kỹ thuật (tùy chọn)
        └── specs&amp;#x2F;
            └── auth&amp;#x2F;
                └── spec.md   # Delta cho thấy phần được thêm
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Đặc tả do AI tạo&lt;&#x2F;strong&gt; (trong &lt;code&gt;openspec&#x2F;specs&#x2F;auth&#x2F;spec.md&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# Đặc tả Xác thực

## Mục đích
Xác thực người dùng và quản lý phiên.

## Yêu cầu
### Yêu cầu: Xác thực người dùng
Hệ thống PHẢI cấp một JWT khi đăng nhập thành công.

#### Kịch bản: Thông tin đăng nhập hợp lệ
- KHI người dùng gửi thông tin hợp lệ
- THÌ một JWT được trả về
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Delta thay đổi do AI tạo&lt;&#x2F;strong&gt; (trong &lt;code&gt;openspec&#x2F;changes&#x2F;add-2fa&#x2F;specs&#x2F;auth&#x2F;spec.md&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# Delta cho Xác thực

## YÊU CẦU ĐƯỢC THÊM
### Yêu cầu: Xác thực hai yếu tố
Hệ thống PHẢI yêu cầu yếu tố thứ hai trong quá trình đăng nhập.

#### Kịch bản: Yêu cầu OTP
- KHI người dùng gửi thông tin hợp lệ
- THÌ hệ thống yêu cầu xác minh OTP
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Nhiệm vụ do AI tạo&lt;&#x2F;strong&gt; (trong &lt;code&gt;openspec&#x2F;changes&#x2F;add-2fa&#x2F;tasks.md&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;## 1. Thiết lập cơ sở dữ liệu
- [ ] 1.1 Thêm cột bí mật OTP vào bảng người dùng
- [ ] 1.2 Tạo bảng ghi nhật ký xác minh OTP

## 2. Triển khai backend
- [ ] 2.1 Thêm endpoint tạo OTP
- [ ] 2.2 Sửa luồng đăng nhập để yêu cầu OTP
- [ ] 2.3 Thêm endpoint xác minh OTP

## 3. Cập nhật frontend
- [ ] 3.1 Tạo component nhập OTP
- [ ] 3.2 Cập nhật giao diện luồng đăng nhập
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quan trọng&lt;&#x2F;strong&gt;: Mày &lt;strong&gt;không tạo các file này thủ công&lt;&#x2F;strong&gt;. Trợ lý AI tạo chúng dựa trên yêu cầu của mày và codebase hiện có.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;original-files&quot;&gt;Original Files&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cong cu&#x2F;ai&#x2F;openspec&#x2F;openspec.md&lt;&#x2F;code&gt; - Document chính&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;cong cu&#x2F;ai&#x2F;openspec&#x2F;hdsd openspec.md&lt;&#x2F;code&gt; - Hướng dẫn chi tiết&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Pi</title>
        <published>2026-04-29T00:00:00+00:00</published>
        <updated>2026-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/pi/"/>
        <id>https://quoc.app/write/pi/</id>
        
        <content type="html" xml:base="https://quoc.app/write/pi/">&lt;div lang=&quot;en&quot;&gt;
&lt;h2 id=&quot;general-information&quot;&gt;General information&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;system-prompt&quot;&gt;System prompt&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;1. skill: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\skills.md
2. extension: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\extensions.md
3. command (prompt): C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\prompt-templates.md
4. readme: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\README.md
5. examples folder: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\examples\extensions\
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;question&quot;&gt;Question?&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Can the UI language be configured to Vietnamese? → No.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;system-configuration&quot;&gt;System configuration&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;1. Global settings: C:\Users\quocn\.pi\agent\settings.json
2. auth&amp;#x2F;API key&amp;#x2F;OAuth token: C:\Users\quocn\.pi\agent1\auth.json
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;shortcuts&quot;&gt;Shortcuts&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@&lt;&#x2F;code&gt; fuzzy-searches files in the current project&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Shift+Enter&lt;&#x2F;code&gt; inserts a new line&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Alt v&lt;&#x2F;code&gt; reads images&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl c&lt;&#x2F;code&gt; clears the current input&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl u&lt;&#x2F;code&gt; clears one line&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl enter&lt;&#x2F;code&gt; inserts a new line&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;commands&quot;&gt;Commands&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt;: reload keybindings, extensions, skills, and prompts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;model&lt;&#x2F;code&gt;: switch the current model&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;new&lt;&#x2F;code&gt;: create a truly new session, without old context&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;resume&lt;&#x2F;code&gt;: reopen an old session&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;copy&lt;&#x2F;code&gt;: copy the agent&#x27;s last response&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;session&lt;&#x2F;code&gt;: view current session info, including the jsonl file&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;quit&lt;&#x2F;code&gt;: exit Pi&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;compact&lt;&#x2F;code&gt;: compact context&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&#x2F;tree&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; = move around the existing &lt;strong&gt;conversation tree&lt;&#x2F;strong&gt; (open the branch map and jump between branches) → does not create a new session, does not delete code
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No summary&lt;&#x2F;strong&gt;: the old branch is no longer in model context; it only remains in the session&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Summarize&lt;&#x2F;strong&gt; &#x2F; &lt;strong&gt;Summarize with custom prompt&lt;&#x2F;strong&gt;: the old branch is no longer full context, but Pi compresses it into a summary and carries some of it forward&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&#x2F;fork&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; = create a &lt;strong&gt;new branch&lt;&#x2F;strong&gt; from an earlier point, then continue in a different direction
&lt;ul&gt;
&lt;li&gt;old branch: &lt;code&gt;a -&amp;gt; b -&amp;gt; c -&amp;gt; d&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;new branch: &lt;code&gt;a -&amp;gt; b -&amp;gt; e -&amp;gt; f&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;In other words, it is tree navigation plus a split into a new branch&#x2F;session. It does not carry the context from &lt;code&gt;c&lt;&#x2F;code&gt; and &lt;code&gt;d&lt;&#x2F;code&gt;; the code stays intact.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;settings&lt;&#x2F;code&gt;: open settings. Press Enter to select.
&lt;ul&gt;
&lt;li&gt;thinking level: higher means smarter, slower, and usually more expensive&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;compact&quot;&gt;Compact&lt;&#x2F;h3&gt;
&lt;p&gt;When context is full, Pi creates a structured summary and keeps the most recent part so the session can continue. Default &lt;code&gt;reserveTokens = 16384&lt;&#x2F;code&gt;, meaning Pi always reserves room for the model to answer.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;↑1.8M ↓82k R25M $10.838 121.2%&amp;#x2F;200k (auto) &amp;gt; it will compact
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;reserves room for the next answer&lt;&#x2F;li&gt;
&lt;li&gt;keeps recent chat intact, summarizes older chat into a structured summary&lt;&#x2F;li&gt;
&lt;li&gt;reloads context: system prompt + summary + recent chat&lt;&#x2F;li&gt;
&lt;li&gt;the jsonl history file is not cleared. Every compact summarizes all old content since the previous compaction.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;settings&quot;&gt;Settings&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Enable images:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;File:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\quocn\.pi\agent\settings.json
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Change:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;blockImages&amp;quot;: true
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;to:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;blockImages&amp;quot;: false
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;then run &lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;command-pi-calls-it-prompt-template&quot;&gt;Command (Pi calls it Prompt template)&lt;&#x2F;h2&gt;
&lt;p&gt;File:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\quocn\.pi\agent\prompts\demo.md
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Content:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Explain the following topic briefly and clearly, with examples if needed:
$@
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then type:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;#x2F;demo Agents
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi expands the template into a full prompt and sends it to the model.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Explain the following topic briefly and clearly, with examples if needed: Agents
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; If there is no &lt;code&gt;$@&lt;&#x2F;code&gt;, the template will not receive the extra text after the command. The final prompt becomes only:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Explain the following topic briefly and clearly, with examples if needed:
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;skill&quot;&gt;Skill&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;reuse-claude-code-skills-in-pi&quot;&gt;Reuse Claude Code skills in Pi&lt;&#x2F;h3&gt;
&lt;p&gt;File: &lt;code&gt;C:\Users\quocn\.pi\agent\settings.json&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Add a &lt;code&gt;skills&lt;&#x2F;code&gt; array that points to the Claude Code skills folder:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;enableSkillCommands&amp;quot;: true,
  &amp;quot;skills&amp;quot;: [
    &amp;quot;D:&amp;#x2F;.claude&amp;#x2F;skills&amp;quot;
  ]
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi will automatically discover every skill in &lt;code&gt;D:\.claude\skills\&lt;&#x2F;code&gt;. No need to copy them into &lt;code&gt;~\.pi\agent\skills\&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-are-commands-different-from-skills&quot;&gt;How are commands different from skills?&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Similarity: both are text and both can contain a workflow.&lt;&#x2F;li&gt;
&lt;li&gt;Command: a short markdown prompt file. When called, Pi expands it into a prompt and sends it to the model. It is a reusable prompt.&lt;&#x2F;li&gt;
&lt;li&gt;Skill: a packaged capability. The model decides to use it when the task matches. A skill can include references, steps, detection rules, and optimized workflows.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;extension&quot;&gt;Extension&lt;&#x2F;h2&gt;
&lt;p&gt;Definition: an extension is TypeScript code that runs inside Pi to extend Pi&#x27;s runtime behavior.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;skill = teaches the model what to do: “How should the LLM handle this task?”&lt;&#x2F;li&gt;
&lt;li&gt;extension = gives Pi extra capabilities
&lt;ul&gt;
&lt;li&gt;TypeScript file loaded at runtime&lt;&#x2F;li&gt;
&lt;li&gt;can listen to events, intercept tools, add commands, add tools, change UI, send notifications, store state&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So it is like the agent&#x27;s tools and limbs. It can run when a session starts, when the agent starts answering, when an answer finishes, when a tool is called, or when a tool result returns.&lt;&#x2F;p&gt;
&lt;p&gt;Think of it like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Model = the brain that answers&lt;&#x2F;li&gt;
&lt;li&gt;Skill = playbook&#x2F;instructions for the brain&lt;&#x2F;li&gt;
&lt;li&gt;Extension = mod&#x2F;plugin attached to Pi&#x27;s body&lt;&#x2F;li&gt;
&lt;li&gt;Settings = system knobs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Example: Windows notification extension&lt;&#x2F;p&gt;
&lt;p&gt;Pi starts → loads extension (TypeScript file) → extension registers event hooks (&lt;code&gt;pi.on(&quot;agent_end&quot;, ...)&lt;&#x2F;code&gt;) → when runtime reaches that event, the extension is called.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div lang=&quot;vi&quot;&gt;
&lt;h2 id=&quot;thong-tin-chung&quot;&gt;Thông tin chung&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;prompt-he-thong&quot;&gt;Prompt hệ thống&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;1. skill: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\skills.md
2. extension: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\extensions.md
3. command (prompt): C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\docs\prompt-templates.md
4. readme: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\README.md
5. thư mục ví dụ: C:\Users\quocn\AppData\Roaming\npm\node_modules\@mariozechner\pi-coding-agent\examples\extensions\
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;cau-hoi&quot;&gt;Câu hỏi?&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Có cấu hình tiếng Việt được không → Không.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;cau-hinh-he-thong&quot;&gt;Cấu hình hệ thống&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;1. Global settings: C:\Users\quocn\.pi\agent\settings.json
2. auth&amp;#x2F;API key&amp;#x2F;OAuth token: C:\Users\quocn\.pi\agent1\auth.json
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;phim-tat&quot;&gt;Phím tắt&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@&lt;&#x2F;code&gt; để fuzzy-search file trong project&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Shift+Enter&lt;&#x2F;code&gt; để xuống dòng&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Alt v&lt;&#x2F;code&gt; đọc hình ảnh&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl c&lt;&#x2F;code&gt; clear nội dung đang gõ&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl u&lt;&#x2F;code&gt; clear 1 dòng&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;ctrl enter&lt;&#x2F;code&gt; xuống dòng&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;lenh&quot;&gt;Lệnh&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt;: dùng để tải lại keybindings, extensions, skills, prompts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;model&lt;&#x2F;code&gt;: đổi model đang dùng&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;new&lt;&#x2F;code&gt;: tạo session mới thật sự, không có ngữ cảnh cũ&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;resume&lt;&#x2F;code&gt;: mở lại session cũ&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;copy&lt;&#x2F;code&gt;: copy câu trả lời cuối của agent&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;session&lt;&#x2F;code&gt;: xem thông tin của session hiện tại, cả file jsonl&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;quit&lt;&#x2F;code&gt;: thoát Pi&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;compact&lt;&#x2F;code&gt;: nén ngữ cảnh&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&#x2F;tree&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; = đi lại trong &lt;strong&gt;cây hội thoại hiện có&lt;&#x2F;strong&gt; (mở bản đồ các nhánh đã có rồi nhảy qua nhảy lại) → không tạo session mới, không xoá code
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No summary&lt;&#x2F;strong&gt;: nhánh cũ không còn trong ngữ cảnh model, chỉ còn trong session&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Summarize&lt;&#x2F;strong&gt; &#x2F; &lt;strong&gt;Summarize with custom prompt&lt;&#x2F;strong&gt;: nhánh cũ không còn nguyên context, nhưng được nén lại thành summary rồi mang theo một phần&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&#x2F;fork&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; = tạo &lt;strong&gt;nhánh mới&lt;&#x2F;strong&gt; từ một điểm cũ để đi hướng khác
&lt;ul&gt;
&lt;li&gt;nhánh cũ: &lt;code&gt;a -&amp;gt; b -&amp;gt; c -&amp;gt; d&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;nhánh mới: &lt;code&gt;a -&amp;gt; b -&amp;gt; e -&amp;gt; f&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Tức nó là tree + tách ra thành nhánh&#x2F;session mới. Không có ngữ cảnh &lt;code&gt;c&lt;&#x2F;code&gt; và &lt;code&gt;d&lt;&#x2F;code&gt;, code vẫn còn nguyên.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;settings&lt;&#x2F;code&gt;: mở setting cấu hình. Enter để chọn.
&lt;ul&gt;
&lt;li&gt;thinking level: càng cao càng thông minh, chậm hơn và thường tốn hơn&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;compact-1&quot;&gt;Compact&lt;&#x2F;h3&gt;
&lt;p&gt;Khi context đầy, Pi tóm tắt thành một summary có cấu trúc rồi giữ lại phần mới nhất để tiếp tục. Mặc định &lt;code&gt;reserveTokens = 16384&lt;&#x2F;code&gt;, tức nó luôn chừa một khoảng trống để model còn chỗ trả lời.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;↑1.8M ↓82k R25M $10.838 121.2%&amp;#x2F;200k (auto) &amp;gt; nó sẽ compact
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;chừa chỗ cho trả lời mới&lt;&#x2F;li&gt;
&lt;li&gt;giữ nguyên đoạn chat gần đây, phần cũ tóm tắt thành summary có cấu trúc&lt;&#x2F;li&gt;
&lt;li&gt;nạp lại ngữ cảnh: hệ thống prompt + summary + đoạn chat gần đây&lt;&#x2F;li&gt;
&lt;li&gt;lịch sử trong file jsonl không bị clear. Mỗi lần compact, nó tóm tắt lại toàn bộ phần cũ tính từ compaction trước đó.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;setting&quot;&gt;Setting&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;Bật hình ảnh:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;File:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\quocn\.pi\agent\settings.json
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Đổi:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;blockImages&amp;quot;: true
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;thành:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;blockImages&amp;quot;: false
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Sau đó chạy &lt;code&gt;&#x2F;reload&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;command-pi-goi-la-prompt-template&quot;&gt;Command (Pi gọi là Prompt template)&lt;&#x2F;h2&gt;
&lt;p&gt;File:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\quocn\.pi\agent\prompts\demo.md
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nội dung:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Giải thích ngắn gọn về chủ đề sau theo kiểu dễ hiểu, có ví dụ nếu cần:
$@
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rồi gõ:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;&amp;#x2F;demo Agents
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi sẽ bung template này thành prompt hoàn chỉnh rồi gửi cho model.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Giải thích ngắn gọn về chủ đề sau theo kiểu dễ hiểu, có ví dụ nếu cần: Agents
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Lưu ý:&lt;&#x2F;strong&gt; Nếu không có &lt;code&gt;$@&lt;&#x2F;code&gt; thì nó sẽ không nhận thêm nội dung phía sau, lúc đó chỉ còn là:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Giải thích ngắn gọn về chủ đề sau theo kiểu dễ hiểu, có ví dụ nếu cần:
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;skill-1&quot;&gt;Skill&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;dung-chung-skill-voi-claude-code&quot;&gt;Dùng chung skill với Claude Code&lt;&#x2F;h3&gt;
&lt;p&gt;File: &lt;code&gt;C:\Users\quocn\.pi\agent\settings.json&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thêm mảng &lt;code&gt;skills&lt;&#x2F;code&gt; trỏ sang thư mục Claude Code:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;enableSkillCommands&amp;quot;: true,
  &amp;quot;skills&amp;quot;: [
    &amp;quot;D:&amp;#x2F;.claude&amp;#x2F;skills&amp;quot;
  ]
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pi sẽ tự động discover tất cả skill trong &lt;code&gt;D:\.claude\skills\&lt;&#x2F;code&gt;. Không cần copy sang &lt;code&gt;~\.pi\agent\skills\&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;command-khac-skill-cho-nao&quot;&gt;Command khác skill chỗ nào?&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Giống: đều là text, có workflow.&lt;&#x2F;li&gt;
&lt;li&gt;Command: file markdown ngắn. Khi gọi, Pi bung nó ra thành prompt và gửi cho model. Nói ngắn gọn, command là prompt tái sử dụng.&lt;&#x2F;li&gt;
&lt;li&gt;Skill: một gói kỹ năng được đóng gói. Model tự quyết định dùng khi task khớp. Skill có thể có thư mục tham khảo, bước làm, cách nhận diện, và workflow tối ưu.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;extension-1&quot;&gt;Extension&lt;&#x2F;h2&gt;
&lt;p&gt;Định nghĩa: extension là code TypeScript chạy cùng Pi để mở rộng hành vi của chính Pi.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;skill = dạy model nên làm gì: “LLM nên xử lý task này theo cách nào?”&lt;&#x2F;li&gt;
&lt;li&gt;extension = dạy Pi có thêm khả năng gì
&lt;ul&gt;
&lt;li&gt;file TypeScript, load lúc runtime&lt;&#x2F;li&gt;
&lt;li&gt;nghe event, chặn tool, thêm command, thêm tool, đổi UI, notify, lưu state&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Tức nó giống như công cụ, cái cuốc cái xẻng cho agent. Nó có thể nhảy vào lúc bắt đầu phiên, lúc agent bắt đầu trả lời, lúc kết thúc trả lời, lúc gọi công cụ, hoặc lúc trả kết quả từ công cụ.&lt;&#x2F;p&gt;
&lt;p&gt;Nhìn như thế này:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Model = bộ não trả lời&lt;&#x2F;li&gt;
&lt;li&gt;Skill = playbook&#x2F;hướng dẫn cho bộ não&lt;&#x2F;li&gt;
&lt;li&gt;Extension = mod&#x2F;plugin gắn vào cơ thể Pi&lt;&#x2F;li&gt;
&lt;li&gt;Settings = núm chỉnh hệ thống&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Ví dụ: extension bắn thông báo Windows&lt;&#x2F;p&gt;
&lt;p&gt;Pi khởi động → load extension (file TypeScript) → extension đăng ký event hooks (&lt;code&gt;pi.on(&quot;agent_end&quot;, ...)&lt;&#x2F;code&gt;) → khi runtime chạy tới event tương ứng, extension được gọi.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Markdown</title>
        <published>2025-12-10T00:00:00+00:00</published>
        <updated>2025-12-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/markdown/"/>
        <id>https://quoc.app/write/markdown/</id>
        
        <content type="html" xml:base="https://quoc.app/write/markdown/">&lt;div lang=&quot;en&quot;&gt;
&lt;h2 id=&quot;basic-syntax&quot;&gt;Basic syntax&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;heading&quot;&gt;Heading&lt;&#x2F;h3&gt;
&lt;p&gt;A line that starts with &lt;code&gt;#&lt;&#x2F;code&gt; is a heading. More &lt;code&gt;#&lt;&#x2F;code&gt; means a smaller heading.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# H1 - Largest
## H2 - Medium
### H3 - Small
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;text-formatting&quot;&gt;Text formatting&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;**bold**
*italic*
~~strikethrough~~
`code`
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;lists&quot;&gt;Lists&lt;&#x2F;h3&gt;
&lt;p&gt;Use &lt;code&gt;-&lt;&#x2F;code&gt; for bullets and numbers for ordered lists. Indent to nest items.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;1. Numbered item
2. Second item
   1. Nested item

- Bullet point
- Another bullet
  - Nested bullet
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;links-and-images&quot;&gt;Links and images&lt;&#x2F;h3&gt;
&lt;p&gt;Images use the same syntax as links, with &lt;code&gt;!&lt;&#x2F;code&gt; in front.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[Text link](https:&amp;#x2F;&amp;#x2F;example.com)
![Image description](&amp;#x2F;path&amp;#x2F;to&amp;#x2F;image.png)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;todo&quot;&gt;Todo&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;- [ ] Not done
- [x] Done
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;code-block&quot;&gt;Code block&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;```
def hello():
    print(&amp;quot;Hello&amp;quot;)
```
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;tables&quot;&gt;Tables&lt;&#x2F;h3&gt;
&lt;p&gt;The second line &lt;code&gt;|---|&lt;&#x2F;code&gt; is required. &lt;code&gt;:---&lt;&#x2F;code&gt; aligns left, &lt;code&gt;:---:&lt;&#x2F;code&gt; centers, and &lt;code&gt;---:&lt;&#x2F;code&gt; aligns right.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;| Left | Center | Right |
|:-----|:------:|------:|
| L    | C      | R     |
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;markdown-in-obsidian&quot;&gt;Markdown in Obsidian&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;internal-links&quot;&gt;Internal links&lt;&#x2F;h3&gt;
&lt;p&gt;Obsidian uses &lt;code&gt;[[ ]]&lt;&#x2F;code&gt; instead of &lt;code&gt;[ ]()&lt;&#x2F;code&gt;. It links to another note in the vault.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[[Note name]]
[[Note|Display text]]
[[folder&amp;#x2F;note]]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;frontmatter-for-metadata&quot;&gt;Frontmatter for metadata&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;---&lt;&#x2F;code&gt; block at the top of a file stores metadata. Use it for filtering, search, and queries.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Note title
tags: [topic, project]
date: 2025-12-08
---
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;embed-notes&quot;&gt;Embed notes&lt;&#x2F;h3&gt;
&lt;p&gt;Add &lt;code&gt;!&lt;&#x2F;code&gt; before &lt;code&gt;[[ ]]&lt;&#x2F;code&gt; to show content instead of only linking to it.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;![[Another note]]       # Embed the whole note
![[Note#Section]]       # Embed one section
![[image.png]]          # Embed image
![[image.png|300]]      # Width 300px
![[image.png|300x150]]  # 300x150
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;callout&quot;&gt;Callout&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]

&amp;gt; [!WARNING]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
&lt;div lang=&quot;vi&quot;&gt;
&lt;h2 id=&quot;cu-phap-co-ban&quot;&gt;Cú pháp cơ bản&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;heading-1&quot;&gt;Heading&lt;&#x2F;h3&gt;
&lt;p&gt;Dòng bắt đầu bằng &lt;code&gt;#&lt;&#x2F;code&gt; là heading. Nhiều &lt;code&gt;#&lt;&#x2F;code&gt; hơn thì heading nhỏ hơn.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# H1 - Lớn nhất
## H2 - Trung bình
### H3 - Nhỏ
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;dinh-dang-text&quot;&gt;Định dạng text&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;**in đậm**
*in nghiêng*
~~gạch ngang~~
`code`
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;danh-sach&quot;&gt;Danh sách&lt;&#x2F;h3&gt;
&lt;p&gt;Dùng &lt;code&gt;-&lt;&#x2F;code&gt; cho bullet, số cho thứ tự. Thụt lề để lồng.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;1. Mục đánh số
2. Mục thứ hai
   1. Mục con

- Bullet point
- Bullet khác
  - Bullet lồng
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;link-va-anh&quot;&gt;Link và ảnh&lt;&#x2F;h3&gt;
&lt;p&gt;Ảnh dùng cùng cú pháp với link, nhưng thêm &lt;code&gt;!&lt;&#x2F;code&gt; ở trước.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[Text link](https:&amp;#x2F;&amp;#x2F;example.com)
![Mô tả ảnh](&amp;#x2F;path&amp;#x2F;to&amp;#x2F;image.png)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;todo-1&quot;&gt;Todo&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;- [ ] Chưa xong
- [x] Xong
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;code-block-1&quot;&gt;Code block&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;```
def hello():
    print(&amp;quot;Hello&amp;quot;)
```
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;bang&quot;&gt;Bảng&lt;&#x2F;h3&gt;
&lt;p&gt;Dòng thứ hai &lt;code&gt;|---|&lt;&#x2F;code&gt; là bắt buộc. &lt;code&gt;:---&lt;&#x2F;code&gt; căn trái, &lt;code&gt;:---:&lt;&#x2F;code&gt; căn giữa, &lt;code&gt;---:&lt;&#x2F;code&gt; căn phải.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;| Trái | Giữa | Phải |
|:-----|:----:|-----:|
| L    | C    | R    |
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;markdown-trong-obsidian&quot;&gt;Markdown trong Obsidian&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;link-noi-bo&quot;&gt;Link nội bộ&lt;&#x2F;h3&gt;
&lt;p&gt;Obsidian dùng &lt;code&gt;[[ ]]&lt;&#x2F;code&gt; thay vì &lt;code&gt;[ ]()&lt;&#x2F;code&gt;. Link đến note khác trong vault.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[[Tên note]]
[[Note|Text hiển thị]]
[[folder&amp;#x2F;note]]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;frontmatter-cho-metadata&quot;&gt;Frontmatter cho metadata&lt;&#x2F;h3&gt;
&lt;p&gt;Khối &lt;code&gt;---&lt;&#x2F;code&gt; ở đầu file dùng để lưu metadata. Dùng nó để lọc, search, query.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Tiêu đề note
tags: [chủ đề, dự án]
date: 2025-12-08
---
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;embed-note&quot;&gt;Embed note&lt;&#x2F;h3&gt;
&lt;p&gt;Thêm &lt;code&gt;!&lt;&#x2F;code&gt; trước &lt;code&gt;[[ ]]&lt;&#x2F;code&gt; để hiển thị nội dung thay vì chỉ link.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;![[Note khác]]       # Embed cả note
![[Note#Section]]    # Embed một phần
![[image.png]]       # Embed ảnh
![[image.png|300]]   # Rộng 300px
![[image.png|300x150]] # 300x150
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;callout-1&quot;&gt;Callout&lt;&#x2F;h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; [!NOTE]

&amp;gt; [!WARNING]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Zola</title>
        <published>2025-12-09T00:00:00+00:00</published>
        <updated>2025-12-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/zola/"/>
        <id>https://quoc.app/write/zola/</id>
        
        <content type="html" xml:base="https://quoc.app/write/zola/">&lt;div lang=&quot;en&quot;&gt;
&lt;h2 id=&quot;what-is-zola&quot;&gt;What is Zola&lt;&#x2F;h2&gt;
&lt;p&gt;Zola is a static site generator written in Rust. You write Markdown, run &lt;code&gt;zola build&lt;&#x2F;code&gt;, and get HTML. No server, no database, no backend.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;# Windows
choco install zola
# macOS
brew install zola
# Linux
snap install --edge zola
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre&gt;&lt;code&gt;zola --version
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;project-structure&quot;&gt;Project structure&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;my-blog&amp;#x2F;
├── config.toml      # Site settings
├── content&amp;#x2F;         # Posts (Markdown)
│   └── write&amp;#x2F;
│       └── post.md
├── templates&amp;#x2F;       # HTML layouts
├── sass&amp;#x2F;            # Styles
└── static&amp;#x2F;          # Images and static files
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;create-a-new-site&quot;&gt;Create a new site&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;zola init my-blog
cd my-blog
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola asks a few questions: URL, syntax highlighting, search. You can change all of that later in &lt;code&gt;config.toml&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;write-a-post&quot;&gt;Write a post&lt;&#x2F;h2&gt;
&lt;p&gt;Create &lt;code&gt;content&#x2F;write&#x2F;post.md&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;+++
title = &amp;quot;Post title&amp;quot;
date = 2025-12-07
+++

Write the content in Markdown.
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;+++&lt;&#x2F;code&gt; block is metadata. Title is the heading, date is used for sorting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preview&quot;&gt;Preview&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;zola serve
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Open &lt;code&gt;http:&#x2F;&#x2F;127.0.0.1:1111&lt;&#x2F;code&gt;. Edit a file, save it, and the page refreshes automatically.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;important-config&quot;&gt;Important config&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;base_url = &amp;quot;https:&amp;#x2F;&amp;#x2F;yourdomain.com&amp;quot;
title = &amp;quot;Blog name&amp;quot;

compile_sass = true
minify_html = true

taxonomies = [
    {name = &amp;quot;tags&amp;quot;, feed = true}
]

generate_feeds = true
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tags-for-posts&quot;&gt;Tags for posts&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;+++
title = &amp;quot;A post about Python&amp;quot;
date = 2025-12-07

[taxonomies]
tags = [&amp;quot;python&amp;quot;, &amp;quot;programming&amp;quot;]
+++
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola automatically creates &lt;code&gt;&#x2F;tags&#x2F;python&#x2F;&lt;&#x2F;code&gt;, listing every post with that tag.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploy-to-netlify&quot;&gt;Deploy to Netlify&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;git init
git add .
git commit -m &amp;quot;Initial commit&amp;quot;
git push origin main
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Netlify → Add new site → Import from Git:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build command: &lt;code&gt;zola build&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Publish directory: &lt;code&gt;public&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Every push triggers a Netlify build and deploy. About 30 seconds from push to live.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cost&quot;&gt;Cost&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Domain: ~$12&#x2F;year&lt;&#x2F;li&gt;
&lt;li&gt;Hosting: $0 (Netlify free tier)&lt;&#x2F;li&gt;
&lt;li&gt;SSL: $0 (Let&#x27;s Encrypt through Netlify)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;drafts&quot;&gt;Drafts&lt;&#x2F;h2&gt;
&lt;p&gt;Put draft posts in &lt;code&gt;content&#x2F;write&#x2F;drafts&#x2F;&lt;&#x2F;code&gt;. Add this to config:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ignored_content = [&amp;quot;*&amp;#x2F;drafts&amp;#x2F;*&amp;quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola skips them during build. Move the file out of drafts when it is ready to publish.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pagination&quot;&gt;Pagination&lt;&#x2F;h2&gt;
&lt;p&gt;Add this to &lt;code&gt;content&#x2F;write&#x2F;_index.md&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;+++
paginate_by = 10
sort_by = &amp;quot;date&amp;quot;
+++
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola automatically creates &lt;code&gt;&#x2F;write&#x2F;page&#x2F;2&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;write&#x2F;page&#x2F;3&#x2F;&lt;&#x2F;code&gt;, and so on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;images&quot;&gt;Images&lt;&#x2F;h2&gt;
&lt;p&gt;Put images in &lt;code&gt;static&#x2F;images&#x2F;&lt;&#x2F;code&gt;. Reference them in a post:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;![Image description](&amp;#x2F;images&amp;#x2F;photo.jpg)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Use &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; at the beginning. Without it, images can break on nested pages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workflow-recap&quot;&gt;Workflow recap&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;# Write a new post
touch content&amp;#x2F;write&amp;#x2F;new-post.md

# Preview while writing
zola serve

# Push when done
git add .
git commit -m &amp;quot;Add new post&amp;quot;
git push
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Push → Netlify build → Live. That is the whole workflow.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div lang=&quot;vi&quot;&gt;
&lt;h2 id=&quot;zola-la-gi&quot;&gt;Zola là gì&lt;&#x2F;h2&gt;
&lt;p&gt;Static site generator viết bằng Rust. Viết Markdown, chạy &lt;code&gt;zola build&lt;&#x2F;code&gt;, ra HTML. Không cần server, không cần database, không cần backend.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cai-dat&quot;&gt;Cài đặt&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;# Windows
choco install zola
# macOS
brew install zola
# Linux
snap install --edge zola
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre&gt;&lt;code&gt;zola --version
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;cau-truc-project&quot;&gt;Cấu trúc project&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;my-blog&amp;#x2F;
├── config.toml      # Cài đặt site
├── content&amp;#x2F;         # Bài viết (Markdown)
│   └── write&amp;#x2F;
│       └── bai-viet.md
├── templates&amp;#x2F;       # HTML layout
├── sass&amp;#x2F;            # Style
└── static&amp;#x2F;          # Ảnh, file tĩnh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tao-site-moi&quot;&gt;Tạo site mới&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;zola init my-blog
cd my-blog
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hỏi vài câu: URL, syntax highlighting, search. Có thể đổi sau trong &lt;code&gt;config.toml&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;viet-bai&quot;&gt;Viết bài&lt;&#x2F;h2&gt;
&lt;p&gt;Tạo file &lt;code&gt;content&#x2F;write&#x2F;bai-viet.md&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;+++
title = &amp;quot;Tiêu đề bài viết&amp;quot;
date = 2025-12-07
+++

Nội dung viết bằng Markdown.
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Phần &lt;code&gt;+++&lt;&#x2F;code&gt; là metadata. Title là heading, date dùng để sắp xếp.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;preview-1&quot;&gt;Preview&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;zola serve
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Mở &lt;code&gt;http:&#x2F;&#x2F;127.0.0.1:1111&lt;&#x2F;code&gt;. Sửa file, lưu, trang tự refresh.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;config-quan-trong&quot;&gt;Config quan trọng&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;base_url = &amp;quot;https:&amp;#x2F;&amp;#x2F;yourdomain.com&amp;quot;
title = &amp;quot;Tên blog&amp;quot;

compile_sass = true
minify_html = true

taxonomies = [
    {name = &amp;quot;tags&amp;quot;, feed = true}
]

generate_feeds = true
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;tag-cho-bai-viet&quot;&gt;Tag cho bài viết&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;+++
title = &amp;quot;Bài về Python&amp;quot;
date = 2025-12-07

[taxonomies]
tags = [&amp;quot;python&amp;quot;, &amp;quot;programming&amp;quot;]
+++
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola tự tạo trang &lt;code&gt;&#x2F;tags&#x2F;python&#x2F;&lt;&#x2F;code&gt; hiện tất cả bài có tag đó.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploy-len-netlify&quot;&gt;Deploy lên Netlify&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;git init
git add .
git commit -m &amp;quot;Initial commit&amp;quot;
git push origin main
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Netlify → Add new site → Import from Git:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build command: &lt;code&gt;zola build&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Publish directory: &lt;code&gt;public&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Mỗi lần push, Netlify tự build và deploy. 30 giây từ push đến live.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;chi-phi&quot;&gt;Chi phí&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Domain: ~$12&#x2F;năm&lt;&#x2F;li&gt;
&lt;li&gt;Hosting: $0 (Netlify free tier)&lt;&#x2F;li&gt;
&lt;li&gt;SSL: $0 (Let&#x27;s Encrypt qua Netlify)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;draft&quot;&gt;Draft&lt;&#x2F;h2&gt;
&lt;p&gt;Đặt bài nháp vào &lt;code&gt;content&#x2F;write&#x2F;drafts&#x2F;&lt;&#x2F;code&gt;. Thêm vào config:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ignored_content = [&amp;quot;*&amp;#x2F;drafts&amp;#x2F;*&amp;quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Zola bỏ qua khi build. Chuyển file ra khỏi drafts khi sẵn sàng publish.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phan-trang&quot;&gt;Phân trang&lt;&#x2F;h2&gt;
&lt;p&gt;Thêm vào &lt;code&gt;content&#x2F;write&#x2F;_index.md&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;+++
paginate_by = 10
sort_by = &amp;quot;date&amp;quot;
+++
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Tự tạo &lt;code&gt;&#x2F;write&#x2F;page&#x2F;2&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;write&#x2F;page&#x2F;3&#x2F;&lt;&#x2F;code&gt;, v.v.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;anh&quot;&gt;Ảnh&lt;&#x2F;h2&gt;
&lt;p&gt;Đặt vào &lt;code&gt;static&#x2F;images&#x2F;&lt;&#x2F;code&gt;. Tham chiếu trong bài:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;![Mô tả ảnh](&amp;#x2F;images&amp;#x2F;photo.jpg)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Dùng &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; ở đầu. Không có &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; ảnh sẽ hỏng ở các trang khác.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workflow-tong-ket&quot;&gt;Workflow tổng kết&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;# Viết bài mới
touch content&amp;#x2F;write&amp;#x2F;bai-moi.md

# Preview khi viết
zola serve

# Xong thì push
git add .
git commit -m &amp;quot;Thêm bài mới&amp;quot;
git push
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Push → Netlify build → Live. Đó là toàn bộ workflow.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>WezTerm</title>
        <published>2025-12-06T00:00:00+00:00</published>
        <updated>2025-12-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://quoc.app/write/wezterm/"/>
        <id>https://quoc.app/write/wezterm/</id>
        
        <content type="html" xml:base="https://quoc.app/write/wezterm/">&lt;div lang=&quot;en&quot;&gt;
&lt;h2 id=&quot;what-is-wezterm&quot;&gt;What is WezTerm&lt;&#x2F;h2&gt;
&lt;p&gt;A terminal emulator written in Rust. Cross-platform, scriptable with Lua. The main difference from Windows Terminal: you can automate everything with code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;
&lt;p&gt;Download from https:&#x2F;&#x2F;wezfurlong.org&#x2F;wezterm&#x2F;installation.html&lt;&#x2F;p&gt;
&lt;p&gt;Config file: &lt;code&gt;C:\Users\{username}\.wezterm.lua&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Save the file and it auto-reloads — no restart needed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-key-workspace-ctrl-shift-p&quot;&gt;One-key workspace: Ctrl+Shift+P&lt;&#x2F;h2&gt;
&lt;p&gt;Press Ctrl+Shift+P → type a project path → WezTerm opens a Claude tab and an Opencode tab in that directory.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;local wezterm = require &amp;#x27;wezterm&amp;#x27;
local act = wezterm.action

{
  key = &amp;#x27;p&amp;#x27;,
  mods = &amp;#x27;CTRL|SHIFT&amp;#x27;,
  action = act.PromptInputLine{
    description = &amp;#x27;Enter project path (Enter = D:):&amp;#x27;,
    action = wezterm.action_callback(function(window, pane, line)
      local project_path = (line and line ~= &amp;#x27;&amp;#x27;) and line or &amp;#x27;D:&amp;#x27;

      local tab1 = window:mux_window():spawn_tab{ cwd = project_path }
      tab1:active_pane():send_text(&amp;quot;claude\r&amp;quot;)

      local tab2 = window:mux_window():spawn_tab{ cwd = project_path }
      tab2:active_pane():send_text(&amp;quot;opencode\r&amp;quot;)
    end),
  },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Replace &quot;claude&quot; and &quot;opencode&quot; with your own tools. Add more tabs with extra &lt;code&gt;spawn_tab&lt;&#x2F;code&gt; calls.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keybindings&quot;&gt;Keybindings&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;keys = {
  { key = &amp;#x27;w&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.CloseCurrentTab{confirm = false} },
  { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.ActivateTabRelative(1) },
  { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.ActivateTabRelative(-1) },
  { key = &amp;#x27;d&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitHorizontal{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
  { key = &amp;#x27;D&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitVertical{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
  { key = &amp;#x27;LeftArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Left&amp;#x27; },
  { key = &amp;#x27;RightArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Right&amp;#x27; },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Tab &#x2F; Ctrl+Shift+Tab&lt;&#x2F;strong&gt;: Switch tabs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+W&lt;&#x2F;strong&gt;: Close tab without confirmation&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Shift+D&lt;&#x2F;strong&gt;: Split horizontally&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Shift+Shift+D&lt;&#x2F;strong&gt;: Split vertically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Alt+Arrow&lt;&#x2F;strong&gt;: Switch panes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;auto-maximize-on-launch&quot;&gt;Auto-maximize on launch&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;wezterm.on(&amp;#x27;gui-startup&amp;#x27;, function(cmd)
  local tab, pane, window = wezterm.mux.spawn_window(cmd or {})
  window:gui_window():maximize()
end)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;minimal-ui&quot;&gt;Minimal UI&lt;&#x2F;h2&gt;
&lt;p&gt;Disable scrollbar, disable fancy tab bar. Tab bar only visible with more than 1 tab.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;enable_scroll_bar = false,
use_fancy_tab_bar = false,
hide_tab_bar_if_only_one_tab = true,
font = wezterm.font &amp;#x27;Cascadia Code&amp;#x27;,
font_size = 13,
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Darker ANSI colors — easier on the eyes against a white background:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;colors = {
  background = &amp;quot;#FFFFFF&amp;quot;,
  foreground = &amp;quot;#000000&amp;quot;,
  ansi = {
    &amp;quot;#1a1a1a&amp;quot;, &amp;quot;#cc0000&amp;quot;, &amp;quot;#008800&amp;quot;, &amp;quot;#cc6600&amp;quot;,
    &amp;quot;#0066cc&amp;quot;, &amp;quot;#cc00cc&amp;quot;, &amp;quot;#0088aa&amp;quot;, &amp;quot;#666666&amp;quot;,
  },
},
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;workflow&quot;&gt;Workflow&lt;&#x2F;h2&gt;
&lt;p&gt;Every morning:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Open WezTerm (auto-maximizes)&lt;&#x2F;li&gt;
&lt;li&gt;Ctrl+Shift+P → Enter&lt;&#x2F;li&gt;
&lt;li&gt;Claude and Opencode ready in 2 tabs&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;5 seconds. No manual tab creation, no repetitive commands.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;full-config&quot;&gt;Full config&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;local wezterm = require &amp;#x27;wezterm&amp;#x27;
local act = wezterm.action

wezterm.on(&amp;#x27;gui-startup&amp;#x27;, function(cmd)
  local tab, pane, window = wezterm.mux.spawn_window(cmd or {})
  window:gui_window():maximize()
end)

return {
  font = wezterm.font &amp;#x27;Cascadia Code&amp;#x27;,
  font_size = 13,
  default_cwd = &amp;quot;D:\\&amp;quot;,
  default_prog = {&amp;quot;powershell.exe&amp;quot;},

  enable_scroll_bar = false,
  use_fancy_tab_bar = false,
  hide_tab_bar_if_only_one_tab = true,

  colors = {
    background = &amp;quot;#FFFFFF&amp;quot;,
    foreground = &amp;quot;#000000&amp;quot;,
    ansi = {
      &amp;quot;#1a1a1a&amp;quot;, &amp;quot;#cc0000&amp;quot;, &amp;quot;#008800&amp;quot;, &amp;quot;#cc6600&amp;quot;,
      &amp;quot;#0066cc&amp;quot;, &amp;quot;#cc00cc&amp;quot;, &amp;quot;#0088aa&amp;quot;, &amp;quot;#666666&amp;quot;,
    },
  },

  keys = {
    { key = &amp;#x27;w&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.CloseCurrentTab{confirm = false} },
    { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.ActivateTabRelative(1) },
    { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.ActivateTabRelative(-1) },
    { key = &amp;#x27;d&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitHorizontal{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
    { key = &amp;#x27;D&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitVertical{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
    { key = &amp;#x27;LeftArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Left&amp;#x27; },
    { key = &amp;#x27;RightArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Right&amp;#x27; },
    {
      key = &amp;#x27;p&amp;#x27;,
      mods = &amp;#x27;CTRL|SHIFT&amp;#x27;,
      action = act.PromptInputLine{
        description = &amp;#x27;Enter project path (Enter = D:):&amp;#x27;,
        action = wezterm.action_callback(function(window, pane, line)
          local project_path = (line and line ~= &amp;#x27;&amp;#x27;) and line or &amp;#x27;D:&amp;#x27;
          local tab1 = window:mux_window():spawn_tab{ cwd = project_path }
          tab1:active_pane():send_text(&amp;quot;claude\r&amp;quot;)
          local tab2 = window:mux_window():spawn_tab{ cwd = project_path }
          tab2:active_pane():send_text(&amp;quot;opencode\r&amp;quot;)
        end),
      },
    },
  },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
&lt;div lang=&quot;vi&quot;&gt;
&lt;h2 id=&quot;wezterm-la-gi&quot;&gt;WezTerm là gì&lt;&#x2F;h2&gt;
&lt;p&gt;Terminal emulator viết bằng Rust. Cross-platform, script được bằng Lua. Khác biệt chính so với Windows Terminal: tự động hóa được mọi thứ bằng code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cai-dat&quot;&gt;Cài đặt&lt;&#x2F;h2&gt;
&lt;p&gt;Tải từ https:&#x2F;&#x2F;wezfurlong.org&#x2F;wezterm&#x2F;installation.html&lt;&#x2F;p&gt;
&lt;p&gt;Config file: &lt;code&gt;C:\Users\{username}\.wezterm.lua&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Lưu file là tự reload, không cần khởi động lại.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workspace-mot-phim-ctrl-shift-p&quot;&gt;Workspace một phím: Ctrl+Shift+P&lt;&#x2F;h2&gt;
&lt;p&gt;Bấm Ctrl+Shift+P → gõ đường dẫn project → WezTerm tự mở tab Claude và tab Opencode ở thư mục đó.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;local wezterm = require &amp;#x27;wezterm&amp;#x27;
local act = wezterm.action

{
  key = &amp;#x27;p&amp;#x27;,
  mods = &amp;#x27;CTRL|SHIFT&amp;#x27;,
  action = act.PromptInputLine{
    description = &amp;#x27;Enter project path (Enter = D:):&amp;#x27;,
    action = wezterm.action_callback(function(window, pane, line)
      local project_path = (line and line ~= &amp;#x27;&amp;#x27;) and line or &amp;#x27;D:&amp;#x27;

      local tab1 = window:mux_window():spawn_tab{ cwd = project_path }
      tab1:active_pane():send_text(&amp;quot;claude\r&amp;quot;)

      local tab2 = window:mux_window():spawn_tab{ cwd = project_path }
      tab2:active_pane():send_text(&amp;quot;opencode\r&amp;quot;)
    end),
  },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Đổi &quot;claude&quot; và &quot;opencode&quot; thành tool bạn dùng. Muốn thêm tab thì thêm &lt;code&gt;spawn_tab&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;phim-tat&quot;&gt;Phím tắt&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;keys = {
  { key = &amp;#x27;w&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.CloseCurrentTab{confirm = false} },
  { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.ActivateTabRelative(1) },
  { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.ActivateTabRelative(-1) },
  { key = &amp;#x27;d&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitHorizontal{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
  { key = &amp;#x27;D&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitVertical{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
  { key = &amp;#x27;LeftArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Left&amp;#x27; },
  { key = &amp;#x27;RightArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Right&amp;#x27; },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Tab &#x2F; Ctrl+Shift+Tab&lt;&#x2F;strong&gt;: Chuyển tab&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+W&lt;&#x2F;strong&gt;: Đóng tab, không hỏi&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Shift+D&lt;&#x2F;strong&gt;: Split ngang&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ctrl+Shift+Shift+D&lt;&#x2F;strong&gt;: Split dọc&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Alt+mũi tên&lt;&#x2F;strong&gt;: Chuyển pane&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;auto-maximize-khi-mo&quot;&gt;Auto-maximize khi mở&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;wezterm.on(&amp;#x27;gui-startup&amp;#x27;, function(cmd)
  local tab, pane, window = wezterm.mux.spawn_window(cmd or {})
  window:gui_window():maximize()
end)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;giao-dien-toi-gian&quot;&gt;Giao diện tối giản&lt;&#x2F;h2&gt;
&lt;p&gt;Tắt scrollbar, tắt fancy tab bar. Tab bar chỉ hiện khi có nhiều hơn 1 tab.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;enable_scroll_bar = false,
use_fancy_tab_bar = false,
hide_tab_bar_if_only_one_tab = true,
font = wezterm.font &amp;#x27;Cascadia Code&amp;#x27;,
font_size = 13,
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Màu ANSI tối hơn mặc định, đọc đỡ mắt trên nền trắng:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;colors = {
  background = &amp;quot;#FFFFFF&amp;quot;,
  foreground = &amp;quot;#000000&amp;quot;,
  ansi = {
    &amp;quot;#1a1a1a&amp;quot;, &amp;quot;#cc0000&amp;quot;, &amp;quot;#008800&amp;quot;, &amp;quot;#cc6600&amp;quot;,
    &amp;quot;#0066cc&amp;quot;, &amp;quot;#cc00cc&amp;quot;, &amp;quot;#0088aa&amp;quot;, &amp;quot;#666666&amp;quot;,
  },
},
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;workflow-1&quot;&gt;Workflow&lt;&#x2F;h2&gt;
&lt;p&gt;Mỗi sáng:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Mở WezTerm (tự maximize)&lt;&#x2F;li&gt;
&lt;li&gt;Ctrl+Shift+P → Enter&lt;&#x2F;li&gt;
&lt;li&gt;Claude và Opencode sẵn sàng trong 2 tab&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;5 giây. Không mở tab thủ công, không gõ lệnh lặp lại.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;config-day-du&quot;&gt;Config đầy đủ&lt;&#x2F;h2&gt;
&lt;pre&gt;&lt;code&gt;local wezterm = require &amp;#x27;wezterm&amp;#x27;
local act = wezterm.action

wezterm.on(&amp;#x27;gui-startup&amp;#x27;, function(cmd)
  local tab, pane, window = wezterm.mux.spawn_window(cmd or {})
  window:gui_window():maximize()
end)

return {
  font = wezterm.font &amp;#x27;Cascadia Code&amp;#x27;,
  font_size = 13,
  default_cwd = &amp;quot;D:\\&amp;quot;,
  default_prog = {&amp;quot;powershell.exe&amp;quot;},

  enable_scroll_bar = false,
  use_fancy_tab_bar = false,
  hide_tab_bar_if_only_one_tab = true,

  colors = {
    background = &amp;quot;#FFFFFF&amp;quot;,
    foreground = &amp;quot;#000000&amp;quot;,
    ansi = {
      &amp;quot;#1a1a1a&amp;quot;, &amp;quot;#cc0000&amp;quot;, &amp;quot;#008800&amp;quot;, &amp;quot;#cc6600&amp;quot;,
      &amp;quot;#0066cc&amp;quot;, &amp;quot;#cc00cc&amp;quot;, &amp;quot;#0088aa&amp;quot;, &amp;quot;#666666&amp;quot;,
    },
  },

  keys = {
    { key = &amp;#x27;w&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.CloseCurrentTab{confirm = false} },
    { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL&amp;#x27;, action = act.ActivateTabRelative(1) },
    { key = &amp;#x27;Tab&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.ActivateTabRelative(-1) },
    { key = &amp;#x27;d&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitHorizontal{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
    { key = &amp;#x27;D&amp;#x27;, mods = &amp;#x27;CTRL|SHIFT&amp;#x27;, action = act.SplitVertical{domain = &amp;#x27;CurrentPaneDomain&amp;#x27;} },
    { key = &amp;#x27;LeftArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Left&amp;#x27; },
    { key = &amp;#x27;RightArrow&amp;#x27;, mods = &amp;#x27;ALT&amp;#x27;, action = act.ActivatePaneDirection &amp;#x27;Right&amp;#x27; },
    {
      key = &amp;#x27;p&amp;#x27;,
      mods = &amp;#x27;CTRL|SHIFT&amp;#x27;,
      action = act.PromptInputLine{
        description = &amp;#x27;Enter project path (Enter = D:):&amp;#x27;,
        action = wezterm.action_callback(function(window, pane, line)
          local project_path = (line and line ~= &amp;#x27;&amp;#x27;) and line or &amp;#x27;D:&amp;#x27;
          local tab1 = window:mux_window():spawn_tab{ cwd = project_path }
          tab1:active_pane():send_text(&amp;quot;claude\r&amp;quot;)
          local tab2 = window:mux_window():spawn_tab{ cwd = project_path }
          tab2:active_pane():send_text(&amp;quot;opencode\r&amp;quot;)
        end),
      },
    },
  },
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
</feed>
