<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oatnil</title>
    <description>The latest articles on DEV Community by Oatnil (@oatnil).</description>
    <link>https://dev.to/oatnil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3901364%2F169a5621-3dec-4111-904e-f8be3a4db579.jpeg</url>
      <title>DEV Community: Oatnil</title>
      <link>https://dev.to/oatnil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oatnil"/>
    <language>en</language>
    <item>
      <title>Why a Ledger Gets Harder to Continue After One Missing Entry</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Thu, 30 Jul 2026 13:24:49 +0000</pubDate>
      <link>https://dev.to/oatnil/why-a-ledger-gets-harder-to-continue-after-one-missing-entry-1dpf</link>
      <guid>https://dev.to/oatnil/why-a-ledger-gets-harder-to-continue-after-one-missing-entry-1dpf</guid>
      <description>&lt;p&gt;When one entry is missing, the first thing that breaks is often not the monthly report. It is your trust in the ledger.&lt;/p&gt;

&lt;p&gt;You know it is already inaccurate. The next time you open it, adding that one entry is not enough. Did you miss others before it? Did the same purchase appear once in each of two channels? Was the original expense reversed after a refund arrived? If any of those questions remains unanswered, continuing feels like adding numbers to a crooked table.&lt;/p&gt;

&lt;p&gt;That is where many people stop. They still want a record of their spending, but they do not want to spend more time on a result they no longer trust.&lt;/p&gt;

&lt;p&gt;A recent real reconciliation covered four months, several payment and banking channels, and hundreds of existing records. There was no assumption about where the problems would be. The comparison surfaced omissions, duplicates, refunds, and old-data issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some expenses appeared on statements but not in the ledger.&lt;/li&gt;
&lt;li&gt;Some purchases left a record in more than one channel.&lt;/li&gt;
&lt;li&gt;Some recorded expenses were later refunded in full but remained in the totals.&lt;/li&gt;
&lt;li&gt;Some old records had no date, so monthly reports could not see them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Memory is a poor way to reconstruct any of these. Refunds and undated old records are especially difficult because they do not look like errors. They quietly change the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpcezrunp4iqlipywz7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqpcezrunp4iqlipywz7i.png" alt="Cross-channel duplicate: one purchase leaves similar records in two channels and the existing ledger, so it is flagged as a possible duplicate for human confirmation" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reconcile First, Then Change the Ledger
&lt;/h3&gt;

&lt;p&gt;The agent did not read the statements and immediately change the data.&lt;/p&gt;

&lt;p&gt;It first compared the statements with the existing records and produced an analysis: confirmed omissions, possible cross-channel duplicates, possible refunds, and cases that required a decision. At this stage, it presented evidence without writing or deleting anything.&lt;/p&gt;

&lt;p&gt;The human supplied the judgment. Whether a transfer counts as spending, how a refund should be classified, and which of two duplicate records should remain all depend on the owner's accounting rules. The agent wrote and corrected records only after the proposed treatment was approved.&lt;/p&gt;

&lt;p&gt;Writing was not the end. It read the ledger back and checked the resulting count and total against the approved list. For every deduplication or deletion, it retained the record identifier, the reason, and the outcome. A conclusion could be traced back to the original record, and the write itself could be checked for mistakes.&lt;/p&gt;

&lt;p&gt;Auditability matters more than a claim that the work was automatic. If automation says only, “I recorded it for you,” the person still does not know what it missed or merged. Analysis first, approval before writing, and a read-back afterward make the work safe to delegate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdrw9e763ynyhe2s4i7gn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdrw9e763ynyhe2s4i7gn.png" alt="Auditable reconciliation flow: analyze and show evidence, wait for human confirmation, write approved changes, read back and check, then retain the record and reason" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Missing Entry No Longer Means Starting Over
&lt;/h3&gt;

&lt;p&gt;The ledger does not require a perfect daily habit. At the end of the month, the agent can compare statements from different sources with the existing records and surface omissions. Forgetting one entry does not invalidate everything recorded before it.&lt;/p&gt;

&lt;p&gt;Duplicates do not have to be guessed by eye either. Similar times, amounts, and descriptions are only clues. Uncertain matches are listed for a human decision instead of being merged silently.&lt;/p&gt;

&lt;p&gt;The person's work is reduced to the few places that require judgment: defining the rules, reviewing evidence, and confirming the treatment. The agent handles the statement-by-statement comparison, cross-checking, data entry, and read-back.&lt;/p&gt;

&lt;p&gt;When a reconciliation can show what it inspected, what it proposed changing, and what it changed, a missing entry becomes one issue to resolve instead of a reason to abandon the entire ledger.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>personalfinance</category>
      <category>tooling</category>
    </item>
    <item>
      <title>No Server? Your Desktop Is the Server</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sun, 26 Jul 2026 12:27:51 +0000</pubDate>
      <link>https://dev.to/oatnil/no-server-your-desktop-is-the-server-pf6</link>
      <guid>https://dev.to/oatnil/no-server-your-desktop-is-the-server-pf6</guid>
      <description>&lt;p&gt;Where your data lives is a fork in the road when you pick a tool. SaaS is the convenient path: sign up and go, nothing to maintain, at the cost of your data sitting on the provider's servers. UnDercontrol will offer that hosted option too. But if what you want is full data self-custody — tasks, notes, and ledgers stored only on your own devices, where backup means copying a file and migration means moving to another machine — this tutorial is for you.&lt;/p&gt;

&lt;p&gt;Self-custody usually means running your own server, and that is exactly where most people give up. Here is a zero-cost path that skips the server entirely: the UnDercontrol desktop app ships with a full backend and keeps your data in a SQLite file on your own disk; Cloudflare Tunnel exposes that machine to the internet for free; the iOS app connects straight to your own endpoint. Check tasks, jot notes, and log expenses from the subway, while the data itself never lives anywhere but your computer. No public IP, no router port forwarding, and no domain to buy (optional, only if you want a fixed address).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2wg494tbwc3b029hnd0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2wg494tbwc3b029hnd0a.png" alt="Architecture: the desktop app embeds a server, cloudflared dials out to Cloudflare's edge, and iOS reaches it over HTTPS from any network" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Install the desktop app, meet the embedded server
&lt;/h2&gt;

&lt;p&gt;Install the UnDercontrol desktop app (macOS / Windows / Linux) from the &lt;a href="https://oatnil.com/download" rel="noopener noreferrer"&gt;download page&lt;/a&gt;. It is not a web-page shell: a complete Go backend ships inside, and the moment the app starts, a local server is listening on port 8888 (it moves to the next free port if 8888 is taken), storing data as a SQLite file on your own disk.&lt;/p&gt;

&lt;p&gt;On first launch you will see "Welcome to UnDercontrol" and a Start button. One click and you are in: the app auto-creates a local account &lt;code&gt;personal@undercontrol.local&lt;/code&gt; with the default password &lt;code&gt;personal123&lt;/code&gt;, no registration, no invite code. Remember these credentials, you will need them on the phone in step 4. And change the default password before exposing anything to the internet; the Security section below shows how.&lt;/p&gt;

&lt;p&gt;Confirm the server is alive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8888/health
&lt;span class="c"&gt;# {"service":"ud-go-production","status":"healthy"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;healthy&lt;/code&gt;, your "server" is ready. It is the computer you are using right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: One command to reach the internet
&lt;/h2&gt;

&lt;p&gt;Cloudflare Tunnel works by reverse connection: &lt;code&gt;cloudflared&lt;/code&gt; on your computer dials out to Cloudflare's edge, and outside traffic is relayed back through that connection. Because the connection is outbound, you need no public IP and never touch your router settings.&lt;/p&gt;

&lt;p&gt;Install cloudflared:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;cloudflared

&lt;span class="c"&gt;# Windows&lt;/span&gt;
winget &lt;span class="nb"&gt;install &lt;/span&gt;Cloudflare.cloudflared

&lt;span class="c"&gt;# Linux (Debian/Ubuntu): add the repo from https://pkg.cloudflare.com first&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;cloudflared
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudflared tunnel &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:8888
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprc8vbdh6zqhip04l7cx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprc8vbdh6zqhip04l7cx.png" alt="Real terminal output: quick tunnel created, and curl against the public address returns healthy" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few seconds later the terminal prints a random &lt;code&gt;https://xxx.trycloudflare.com&lt;/code&gt; address: your public endpoint, HTTPS included, no Cloudflare account required. Verify from your phone (turn off Wi-Fi so you are on cellular, which proves the path is really public): open &lt;code&gt;https://xxx.trycloudflare.com/health&lt;/code&gt; in the browser. &lt;code&gt;healthy&lt;/code&gt; means the whole chain works.&lt;/p&gt;

&lt;p&gt;Quick tunnels are for trying the flow out: the address changes every time you restart &lt;code&gt;cloudflared&lt;/code&gt;, and Cloudflare makes no uptime promise for them. For daily use, spend five minutes upgrading to a named tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 (recommended): A named tunnel with a fixed address
&lt;/h2&gt;

&lt;p&gt;A named tunnel needs a free Cloudflare account and a domain hosted on Cloudflare. The domain costs a few dollars a year and is the only place money can enter this setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Log in; authorize your domain in the browser&lt;/span&gt;
cloudflared tunnel login

&lt;span class="c"&gt;# 2. Create the tunnel&lt;/span&gt;
cloudflared tunnel create ud

&lt;span class="c"&gt;# 3. Point a subdomain at it&lt;/span&gt;
cloudflared tunnel route dns ud ud.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write a config file at &lt;code&gt;~/.cloudflared/config.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tunnel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ud&lt;/span&gt;
&lt;span class="na"&gt;credentials-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/Users/you/.cloudflared/&amp;lt;tunnel-id&amp;gt;.json&lt;/span&gt;

&lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ud.example.com&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8888&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http_status:404&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it, then register it as a system service so it survives reboots:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cloudflared tunnel run ud        &lt;span class="c"&gt;# run manually first&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;cloudflared service &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="c"&gt;# then install as a service&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From now on &lt;code&gt;https://ud.example.com&lt;/code&gt; is your fixed endpoint. Remember to stop the computer from sleeping in the system power settings — it is your server now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Point the iOS app at your endpoint
&lt;/h2&gt;

&lt;p&gt;The iOS app is in &lt;a href="https://testflight.apple.com/join/st2TnaBF" rel="noopener noreferrer"&gt;public beta on TestFlight&lt;/a&gt; (install TestFlight from the App Store first).&lt;/p&gt;

&lt;p&gt;Open the app. At the bottom of the sign-in screen there is an &lt;strong&gt;API server&lt;/strong&gt; section showing the current server. Tap &lt;strong&gt;Change&lt;/strong&gt; and enter your public address, &lt;strong&gt;including the &lt;code&gt;/api/v1&lt;/code&gt; suffix&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://xxx.trycloudflare.com/api/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status dot probes as you type: when it turns green with &lt;code&gt;connected · Personal&lt;/code&gt;, your phone has reached the server on your computer. Tap &lt;strong&gt;Save&lt;/strong&gt;, then sign in with the account from step 1: &lt;code&gt;personal@undercontrol.local&lt;/code&gt; and your password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hz1yn8in6ixbvwgwafu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hz1yn8in6ixbvwgwafu.png" alt="iOS sign-in screen: API server pointing at the trycloudflare address, status connected · Personal" width="800" height="1739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you see on the phone is the data on your computer: tasks, notes, ledgers. Edit on the phone and the desktop has it.&lt;/p&gt;

&lt;p&gt;One detail: iOS requires HTTPS for public domains (Cloudflare Tunnel provides it, nothing to do). If you enter a LAN or private-mesh IP instead, write &lt;code&gt;http://&lt;/code&gt; explicitly; without a scheme the app assumes &lt;code&gt;https://&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;Public exposure means anyone with the URL can reach your endpoint. Three things, in order of importance:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Change the default password first.&lt;/strong&gt; Every data endpoint requires login, but the desktop's default password &lt;code&gt;personal123&lt;/code&gt; is public knowledge. Exposing it unchanged is taping the key to the door. The password comes from the &lt;code&gt;PERSONAL_TIER_PASSWORD&lt;/code&gt; environment variable; on macOS, launch from a terminal with it set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PERSONAL_TIER_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'your-strong-password'&lt;/span&gt; /Applications/UnderControl.app/Contents/MacOS/UnderControl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows, add &lt;code&gt;PERSONAL_TIER_PASSWORD&lt;/code&gt; in System Environment Variables and restart the app. Phone and CLI then log in with the new password.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A random URL is not a security mechanism.&lt;/strong&gt; The trycloudflare address is hard to guess, but do not treat that as protection; think before sharing the link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. For an extra gate&lt;/strong&gt;, &lt;a href="https://developers.cloudflare.com/cloudflare-one/policies/access/" rel="noopener noreferrer"&gt;Cloudflare Access&lt;/a&gt; on the free plan can put an email-code check in front of a named tunnel. Configure it once and it applies to every device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't want public exposure at all?
&lt;/h2&gt;

&lt;p&gt;If all you need is "my devices can reach each other", skip the public internet entirely: use a private mesh network tool to put your phone and computer on the same virtual LAN. Install the client on each device and they see each other; your computer gets a virtual-LAN IP, and the iOS app endpoint becomes &lt;code&gt;http://&amp;lt;virtual-lan-ip&amp;gt;:8888/api/v1&lt;/code&gt; (write &lt;code&gt;http://&lt;/code&gt; explicitly). Zero public exposure, and the free tiers of these tools are usually plenty for personal use. The mesh setup itself is out of scope here; every vendor's docs cover the phone-plus-computer case.&lt;/p&gt;

&lt;h2&gt;
  
  
  After it works
&lt;/h2&gt;

&lt;p&gt;The bill: VPS $0, tunnel $0, HTTPS certificate $0. The only optional cost is a domain at a few dollars a year.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desktop download: &lt;a href="https://oatnil.com/download" rel="noopener noreferrer"&gt;https://oatnil.com/download&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;iOS TestFlight: &lt;a href="https://testflight.apple.com/join/st2TnaBF" rel="noopener noreferrer"&gt;https://testflight.apple.com/join/st2TnaBF&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>selfhosted</category>
      <category>cloudflare</category>
      <category>ios</category>
    </item>
    <item>
      <title>Pin the Discussion to the Line It's About</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sat, 25 Jul 2026 07:07:48 +0000</pubDate>
      <link>https://dev.to/oatnil/pin-the-discussion-to-the-line-its-about-55mb</link>
      <guid>https://dev.to/oatnil/pin-the-discussion-to-the-line-its-about-55mb</guid>
      <description>&lt;p&gt;You send out a spec and the discussion immediately comes apart from it. Someone replies in Slack: "that field in the third section, is it nullable?" Now you scroll back to the doc, count down to the third section, and guess which field they meant. Read the same message a day later and the context is gone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw2efbngylbik6ilq73le.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw2efbngylbik6ilq73le.png" alt="Anchored comments: discussion pinned to the line it is about" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anchored comments in UnDercontrol keep the discussion next to the original text. Select a sentence in the task body, click Comment in the bubble menu, and a comment carrying that quote appears in the right sidebar while the sentence itself turns into a highlight. Click the highlight later and the sidebar jumps to the matching thread. The quote lives on the comment, so the markdown in the task body is never touched. Copy it out or pull it down from the command line and you get exactly what you wrote.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbouofc7o7j9xueg7lw0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbouofc7o7j9xueg7lw0m.png" alt="A highlighted sentence in the task body with its anchored comment thread open in the sidebar" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a discussion is settled, hit Resolve. The highlight disappears from the body, the thread collapses into a single grey line, and you can reopen it whenever you want. Threads update on their own when someone replies, with no page refresh. On a phone there are no highlights and the comments sit below the body.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewing a spec like you review code
&lt;/h3&gt;

&lt;p&gt;A reviewer no longer has to write "third section, second sentence". They select the line that says "supports bulk import", ask "what's the upper limit?", and the author answers in the same thread. Agree, resolve, move on.&lt;/p&gt;

&lt;p&gt;Once you have been through a spec, the highlights still lit on the page are the parts nobody settled. There is no separate write-up to do afterwards, because the unresolved threads are the to-do list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgke24639ynjw15b5hx0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgke24639ynjw15b5hx0s.png" alt="The comments sidebar after a review pass: resolved threads collapsed, unsettled ones still open" width="776" height="1560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Point at a line and let an agent change it
&lt;/h3&gt;

&lt;p&gt;This is the part that is not like a normal comment section. Select the requirement you want changed, leave a comment that @mentions your agent, and say what it should become. The mention starts an agent session, reusing one that is already running, and when the agent is done its reply is the next comment in that thread, sitting alongside your colleagues' replies with the commit hash in it. Click the highlight and you are back at the text that changed, side by side.&lt;/p&gt;

&lt;p&gt;People and agents talk in one thread, so you are not relaying messages between two tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1xn73vpqs78lnsjx4vys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1xn73vpqs78lnsjx4vys.png" alt="A human comment mentions an agent and the agent replies in the same thread with a commit hash" width="690" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Section-by-section discussion on long documents
&lt;/h3&gt;

&lt;p&gt;Write the task body as a design doc and record each iteration as a note. Discussions anchor to their own section: comments on the body in one group, comments on each note in a group of their own, and unanchored chatter in a third. Three months later, why a decision went the way it did is written next to the sentence it changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The same thread from your terminal
&lt;/h3&gt;

&lt;p&gt;Comments are just as readable and writable from a terminal. The ud CLI treats them as a resource like any other, so an agent can read the discussion a human left in the browser and reply to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# read every discussion on a task&lt;/span&gt;
ud get comments &lt;span class="nt"&gt;--task&lt;/span&gt; 02c137b3

&lt;span class="c"&gt;# reply to a thread&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' | ud apply -f -
---
task_id: 02c137b3
parent_id: 7a1c9f2e
---
Per-user rate limiting is in, commit a1b2c3d4.
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code, Codex, OpenCode, or any terminal-based agent works here without an adapter layer. Close a thread out with &lt;code&gt;ud patch comment &amp;lt;id&amp;gt; --status resolved&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Anchored comments have been available since v0.88.0, in the browser, in the desktop app, and from the CLI.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devtools</category>
      <category>ai</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Turn a Task into a Parcel Locker</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Fri, 24 Jul 2026 10:51:06 +0000</pubDate>
      <link>https://dev.to/oatnil/turn-a-task-into-a-parcel-locker-1ic9</link>
      <guid>https://dev.to/oatnil/turn-a-task-into-a-parcel-locker-1ic9</guid>
      <description>&lt;p&gt;The computer at a print shop isn't yours, and you're not going to log into anything on it. The usual ways to move a file there are all awkward: messaging apps want a QR scan and a login session, cloud-drive share pages nag you to install their app, and the USB stick is at home.&lt;/p&gt;

&lt;p&gt;A task in UnDercontrol is already a container: body text, notes, and file attachments. Generate a public share link for it, and anyone who has the link can read the content and download the files. No account, nothing to install. It works like a parcel locker: you drop things in, get a pickup code, and whoever has the code takes them out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F12tjqk67gxtgdsnhuqli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F12tjqk67gxtgdsnhuqli.png" alt="Concept: a task working as a parcel locker" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: put the files on a task
&lt;/h3&gt;

&lt;p&gt;Create a task and upload the files in its attachments section. The task body is Markdown, so write the instructions right next to the files. Whoever opens the link sees your print requirements, not a bare file list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvxkdc9djr80s7g24lkrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvxkdc9djr80s7g24lkrv.png" alt="Task detail: attachments and print notes" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: generate the share link
&lt;/h3&gt;

&lt;p&gt;Open &lt;strong&gt;Share to Public&lt;/strong&gt; in the task menu. Two settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expiry&lt;/strong&gt;: 1 hour / 1 day / 7 days / never&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow attachment downloads&lt;/strong&gt;: off by default; check it when the point is the files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click Generate Link and you get three things at once: the full link, a 6-letter pickup code, and a pre-composed message (Copy Share Message) that carries both, ready to paste into any chat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswtxx8sfqrsc5uk78zdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswtxx8sfqrsc5uk78zdd.png" alt="Share dialog: link, pickup code, expiry" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: pick up on any device
&lt;/h3&gt;

&lt;p&gt;Three ways in, for three situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You have the link&lt;/strong&gt;: open it. It's a read-only page with the title, body, notes, and attachments, each with a download button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You have only the code&lt;/strong&gt;: open the share entry page and type the 6 letters. Handy when the code was read out loud, or on a public computer where you'd rather not type a long URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You're standing next to the person&lt;/strong&gt;: the share page shows a QR code; scanning it lands on the same page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0yhasu68f10igmo4388.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx0yhasu68f10igmo4388.png" alt="Public share page: QR code, expiry countdown, downloads" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupu9j20gcrkx2eqpdvnh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupu9j20gcrkx2eqpdvnh.png" alt="Pickup code entry page" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The security details
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The token in the link is 32 random bytes (64 hex characters), so it can't be enumerated&lt;/li&gt;
&lt;li&gt;Links expire on schedule. The dialog lists each link's remaining time, and any link can be revoked at any moment&lt;/li&gt;
&lt;li&gt;Attachment downloads go through presigned URLs generated per click and valid for 15 minutes; the file in storage is never public&lt;/li&gt;
&lt;li&gt;The shared page is read-only and carries only the title, body, notes, and attachments. No account info, and comments stay private&lt;/li&gt;
&lt;li&gt;Self-hosted instances can switch public sharing off entirely in system config&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  A parcel locker for documents too
&lt;/h3&gt;

&lt;p&gt;The task body and notes are Markdown, written in the same editor UnDercontrol uses everywhere else (notes, finance records). So the thing you share doesn't have to be a file. Meeting minutes, a PC-build checklist, a travel plan — the other side opens a formatted read-only page. Files and documents travel through the same link.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typical scenarios
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Print shop&lt;/strong&gt;: attach the PDFs, type the pickup code on the shop computer, download and print, revoke the link when you get home&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sending files to someone without an account&lt;/strong&gt;: paste the Copy Share Message; one message carries the link and the code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A shared meeting-room computer&lt;/strong&gt;: type the 6-letter code to open the document read-only; whoever wants a copy afterward scans the QR on the page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliverables for an outside collaborator&lt;/strong&gt;: pick the 7-day expiry and the link shuts off by itself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output from terminal AI agents&lt;/strong&gt; (Claude Code, Codex, OpenCode, or any terminal-based agent): the agent attaches its report and artifacts to a task; you review, then forward one link&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The entry point is Share to Public in the ⋮ menu on the task detail page. Self-hosting? Check that the public share switch in system config is on — it is by default.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>devtools</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Claude Plans, Codex Executes</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sun, 19 Jul 2026 09:26:00 +0000</pubDate>
      <link>https://dev.to/oatnil/claude-plans-codex-executes-3mm1</link>
      <guid>https://dev.to/oatnil/claude-plans-codex-executes-3mm1</guid>
      <description>&lt;p&gt;Plenty of developers already work this way: hash out the approach in Claude Code, then copy the conclusion into Codex to implement. The reason is practical, too — you're paying for both subscriptions anyway. Claude is great at planning; letting Codex do the heavy lifting doesn't burn your Claude quota. Both subscriptions earn their keep. The only problem: the "copy-paste" role in the middle is &lt;em&gt;you&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In UnDercontrol, this pipeline works out of the box&lt;/strong&gt;: Claude plans, Codex executes, and the task system is the whiteboard they share — you only step in to review at the key points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gvbbcja2hg8uawfkxaa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4gvbbcja2hg8uawfkxaa.png" alt="Claude plans, Codex executes — tasks are the shared whiteboard between your AI agents" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Five steps to a working pipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure two agents.&lt;/strong&gt; Claude Code, Codex, and OpenCode are built-in Agent CLI templates — just pick one (any custom command works too). Give the planner Claude Code and the executor Codex. Don't feel like configuring? Even this step can be outsourced — there's a built-in &lt;strong&gt;Agent Creator&lt;/strong&gt;: @mention it, describe the combo you want, and it sets the agents up for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Toss the requirement to the planner.&lt;/strong&gt; A rough task is fine — just @planner it. The daemon spins up a Claude Code session on your dev machine: it reads the description, clarifies the requirement, and splits it into subtasks with acceptance criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The planner delegates to the executor.&lt;/strong&gt; It @executor-mentions each subtask — an agent-to-agent @mention automatically launches a new workspace session for the other agent, and the delegation chain preserves your access scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex executes.&lt;/strong&gt; Each session picks up one subtask: writes code, runs tests, commits, notes progress back on the task, and marks it &lt;code&gt;pending&lt;/code&gt; when done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You step in at exactly two points.&lt;/strong&gt; Approve the plan; review the output.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzwufhogqm86me9bbfqo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzwufhogqm86me9bbfqo8.png" alt="From a rough idea to reviewed commits — one pipeline" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole collaboration happens on the task itself — the description is the spec, comments are the conversation, notes are the progress log. Here's a real task detail: the planner's acceptance criteria on the left, the three-way comment thread on the right:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fesg7jfgmiqbg51nukhsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fesg7jfgmiqbg51nukhsm.png" alt="Task detail — the planner writes the spec, the executor reports commits, everything on the record" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Form a squad: Agent Teams
&lt;/h3&gt;

&lt;p&gt;Don't want to conduct two agents by hand every time? Organize them into a &lt;strong&gt;Team&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A Team has one &lt;strong&gt;lead&lt;/strong&gt; and any number of &lt;strong&gt;members&lt;/strong&gt;, and each member carries a delegation hint — "what kind of work routes here." When the lead's session starts, its roster is injected into the prompt automatically — &lt;strong&gt;the lead is born knowing who reports to it, what each specialist is good at, and how to delegate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmb81iz7kahyirmj9jzki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmb81iz7kahyirmj9jzki.png" alt="Agent Teams — a lead plus members with delegation hints, roster auto-injected into the lead's session" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Claude plans, Codex executes" becomes a one-liner: @mention the dev-team's lead and it arranges the rest. Teams also nest — a member can itself lead another Team, so hierarchy grows naturally while each agent only ever needs to know its direct reports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch everything live
&lt;/h3&gt;

&lt;p&gt;Open a board for the big picture: how much got planned, what's executing, what's waiting for review — one glance. Every agent session's terminal output also streams back to the web in real time — on your laptop, or your phone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F58juox1ul0482cnrenfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F58juox1ul0482cnrenfs.png" alt="The AI team delivery board — Planning / Executing / Pending Review / Done" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Typical scenarios
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Queue work before bed, review after breakfast.&lt;/strong&gt; Drop three feature requests on the planner at night; wake up to split subtasks and several &lt;code&gt;pending&lt;/code&gt; implementations, each with its own commits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slice a big refactor.&lt;/strong&gt; Claude writes the migration plan and cuts it into 20 small tasks; Codex executes them one by one — roll back exactly the step that goes wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A bug-triage pipeline.&lt;/strong&gt; The planner reproduces, localizes, and writes up the root cause before delegating the fix — the executor gets "what to change, why, and how to verify," not "there's a bug, fix it."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The combo is yours to choose
&lt;/h3&gt;

&lt;p&gt;Claude + Codex is just one pairing. UnDercontrol is not tied to any AI tool — Claude Code, Codex, OpenCode, or any terminal-based agent can be a lead or a member. Roles are defined by prompts and skills; tools by Agent CLI configuration. Whatever subscriptions you hold and whatever each model is best at, the orchestration is in your hands.&lt;/p&gt;

&lt;p&gt;One more thing: the progress agents write back lives in the same Markdown system as everything you write by hand — tasks, notes, comments, even finance records share one editing experience.&lt;/p&gt;




&lt;p&gt;Want to try it? &lt;a href="https://oatnil.com/docs/download" rel="noopener noreferrer"&gt;Download UnDercontrol&lt;/a&gt;, start the daemon, create a Team, and @mention the lead on your first task.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>agents</category>
    </item>
    <item>
      <title>Virtual Path: Where Tasks Settle into Knowledge and Docs</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sat, 18 Jul 2026 03:04:01 +0000</pubDate>
      <link>https://dev.to/oatnil/virtual-path-where-tasks-settle-into-knowledge-and-docs-2em2</link>
      <guid>https://dev.to/oatnil/virtual-path-where-tasks-settle-into-knowledge-and-docs-2em2</guid>
      <description>&lt;p&gt;I've watched too many tasks die the moment they hit "Done." The card gets archived and nobody ever opens it again — why we designed it that way, what pitfalls we hit, how it was verified, all buried inside. Two months later someone asks, and you retell it from memory.&lt;/p&gt;

&lt;p&gt;Building UnDercontrol, I've held onto one conviction: a task shouldn't be disposable. Its body is already a Markdown document, its Notes record how it evolved step by step, and the comments keep the arguments from back then. Throwing all of that away when the work is done is just wasteful.&lt;/p&gt;

&lt;p&gt;That's why Virtual Path exists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcabb7z4tzetnmmugt16m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcabb7z4tzetnmmugt16m.png" alt="A task's endpoint isn't Done — it's a place in your knowledge tree" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Give a task a place
&lt;/h3&gt;

&lt;p&gt;The idea is simple: every task, every uploaded file, even every Skill can carry a virtual path like &lt;code&gt;/engineering/backend/&lt;/code&gt;. Everything with a path forms one tree — the Explorer. It looks like a file manager, but there are no real directories underneath. Wherever a path exists, a "folder" exists; delete the contents and the folder disappears on its own. You never have to maintain a pile of empty directories.&lt;/p&gt;

&lt;p&gt;When a task is done and worth keeping, drag it into &lt;code&gt;/decisions/&lt;/code&gt; or &lt;code&gt;/engineering/&lt;/code&gt; — it turns from a finished card into a document in your knowledge base. No copy-pasting into another note app; the Notes and comments stay attached.&lt;/p&gt;

&lt;p&gt;And the ones not worth keeping? Leave them. Unfiled tasks sit at the tree root and in the "Unfiled" area, never mixing into the folders you've organized. The tree is curated, not accumulated — you decide what earns a place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5pqrnfodiwdm5x8k0gpr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5pqrnfodiwdm5x8k0gpr.jpg" alt="Explorer tree + task as document: the knowledge tree on the left, a settled architecture doc on the right" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diagrams, screenshots, whiteboard photos can live at the same path too, so a topic's text and assets sit side by side — no more digging through a cloud drive for "that one image."&lt;/p&gt;

&lt;p&gt;By the way, this isn't just about tasks. Every writing surface in UnDercontrol — tasks, notes, expense records, account memos — shares the same Markdown editor, so any content can settle down the same way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Many tasks, one document
&lt;/h3&gt;

&lt;p&gt;The more common case is this: a topic wraps up after seven or eight tasks, each holding a few scattered findings, none of them usable as a document on its own.&lt;/p&gt;

&lt;p&gt;These days I hand that job to an agent. Claude Code, Codex, OpenCode — any terminal agent can read through the batch via the ud CLI, distill it into one new document, and file it into the right folder of the tree. The original tasks stay untouched, kept as raw material you can always trace back to. What the knowledge base keeps is the distilled conclusion, not a pile of process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sync it local — offline, and yours
&lt;/h3&gt;

&lt;p&gt;Knowledge living on a server is only step one. My own habit: documents must be able to land on my own disk, editable with whatever editor I like.&lt;/p&gt;

&lt;p&gt;The ud CLI syncs git-style (I wrote about the basics before: &lt;a href="https://oatnil.com/blog/2026/07/07/ud-pull-push/" rel="noopener noreferrer"&gt;Manage Your Tasks Like git: ud pull / push&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ud init /Knowledge/   &lt;span class="c"&gt;# bind the current folder to a virtual path&lt;/span&gt;
ud pull               &lt;span class="c"&gt;# tasks become local .md files&lt;/span&gt;
ud push               &lt;span class="c"&gt;# local edits go back to the server&lt;/span&gt;
ud status             &lt;span class="c"&gt;# see what differs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default vault layout is Obsidian-native:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MyVault/
├─ engineering/backend/
│  └─ SSE reconnect backoff.md     ← one .md = one task
├─ notes/SSE reconnect backoff/    ← the task's Notes, grouped per task
│  └─ soak test results.md
├─ attachments/diagram.png         ← resources (--fetch-attachments)
└─ .udignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a pull, this is a fully offline local knowledge base. Plain Markdown on your disk — readable and editable without a connection, works fine on a plane, one &lt;code&gt;ud push&lt;/code&gt; after landing. The data is yours. Both copies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqxzz153j4hh7vx49t0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqxzz153j4hh7vx49t0h.png" alt="vault sync: the virtual path tree on the server ⇄ a local Obsidian vault" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lot of care went into the details; a few worth mentioning: ud writes exactly one &lt;code&gt;ud-id&lt;/code&gt; line into the frontmatter and leaves the rest untouched; rename a file locally and the task title follows after a push; &lt;code&gt;[[wikilinks]]&lt;/code&gt; written in Obsidian get translated into ud's &lt;code&gt;task://&lt;/code&gt; links on push and back again on pull, so clicking works on both sides; files you don't want synced go into &lt;code&gt;.udignore&lt;/code&gt;, gitignore syntax; conflicts are handled git-style — items changed on both sides get flagged and skipped by default, never silently overwritten. And moving over from the older folder structure is a single &lt;code&gt;ud migrate-layout&lt;/code&gt; away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let an agent tidy your tree
&lt;/h3&gt;

&lt;p&gt;Every knowledge base gets messy over time. Folders grow deeper, names drift, stale docs mix with fresh ones — mine too.&lt;/p&gt;

&lt;p&gt;But tidying is exactly the kind of bulk work agents are best at. The vault is just a local folder: after &lt;code&gt;ud pull&lt;/code&gt;, let an agent read the whole tree — restructure folders, merge duplicates, unify naming, move the stale stuff into an archive. All it does is ordinary file operations; you review the diff with git or &lt;code&gt;ud status&lt;/code&gt;, then &lt;code&gt;ud push&lt;/code&gt; when satisfied. The Explorer on the web immediately shows the tidied shape.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn15h0oygochrihcpg7ax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn15h0oygochrihcpg7ax.png" alt="Layered model: the content layer is your vault, the collaboration layer is ud's overlay" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What makes it safe to let an agent loose here is the clean layering: the vault layer is content — plain text, git-able, anyone can edit it; status, boards, comments, and the Notes timeline are ud's collaboration metadata sitting on top, the way PR comments never get written into the git tree. The agent touches the content layer; the collaboration history loses nothing.&lt;/p&gt;

&lt;p&gt;And a tidied tree isn't locked to one machine. Web, desktop, and mobile all see the same tree: skim an ADR on your phone during the commute, edit properly on the web at your desk, hand batch work to the CLI and agents in the terminal. Organize once, use it anywhere.&lt;/p&gt;




&lt;p&gt;A task's endpoint shouldn't be "Done." Give the things worth keeping a place in your knowledge tree — one drag, one command, or hand it to your agent.&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>productivity</category>
      <category>obsidian</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Growing with UnDercontrol: Time Compounds, and So Does Knowledge</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Fri, 17 Jul 2026 05:06:57 +0000</pubDate>
      <link>https://dev.to/oatnil/growing-with-undercontrol-time-compounds-and-so-does-knowledge-4ac2</link>
      <guid>https://dev.to/oatnil/growing-with-undercontrol-time-compounds-and-so-does-knowledge-4ac2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs1wthjmhfn67gy2quyd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs1wthjmhfn67gy2quyd3.png" alt="The compounding curve of knowledge" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I studied architecture. Then I switched careers and became a programmer. Later I left everything familiar behind and moved to Singapore, where I now work as a fullstack / DevOps engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Career switchers know what "accumulation" really means
&lt;/h3&gt;

&lt;p&gt;Switching careers means starting from zero: no four years of CS coursework to lean on — every concept had to be chewed through on my own. That's when I picked up a habit: write down every pitfall I hit, every concept that finally clicked, every config I got working. Not out of diligence — out of fear. If I didn't write it down today, I'd pay for it again tomorrow.&lt;/p&gt;

&lt;p&gt;Looking back, that habit is the highest-return investment I've ever made. It carried me through the career switch, through job changes, through moving countries, and eventually through building my own product. Knowledge, like money, compounds — but only if you have an account for it to grow in.&lt;/p&gt;

&lt;p&gt;Over the years, my "account" changed three times: Joplin → Obsidian → UnDercontrol. Each migration wasn't chasing something shiny — it was my understanding of &lt;em&gt;how knowledge should work&lt;/em&gt; leveling up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9wi5ie7fx4v7i5l0cq6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl9wi5ie7fx4v7i5l0cq6.png" alt="Two journeys, one habit" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Joplin era: get things written down (Collect)
&lt;/h3&gt;

&lt;p&gt;My first stop was Joplin. Open source, free, Markdown, encrypted sync — for someone just getting serious about notes, it solved the most important problem: &lt;strong&gt;making "write it down" actually happen&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My early study notes, interview prep, and debugging logs from the career-switch years all piled up there.&lt;/p&gt;

&lt;p&gt;But over time, the notes felt like drawers: easy to put things in, but every note lived in isolation. The notes themselves sat inside the app's database; finding things meant folders and keyword search; there were no real connections between notes. The knowledge was stored — but it just lay there. It didn't appreciate.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Obsidian era: connect the knowledge (Connect)
&lt;/h3&gt;

&lt;p&gt;So I moved to Obsidian: plain local Markdown files, bidirectional links, a knowledge graph, a rich plugin ecosystem.&lt;/p&gt;

&lt;p&gt;This was a genuine upgrade. For the first time, my notes went from "a pile of files" to "a network" — writing something new naturally pulled old notes in. My vault passed a thousand notes in this era, and I could feel the accumulated weight supporting me in retrospectives, in writing, in technical decisions.&lt;/p&gt;

&lt;p&gt;The career switch and the move abroad — the two biggest jumps of my life — were both backed by the same body of notes. That was the first time "the compound interest of knowledge" stopped being a platitude for me.&lt;/p&gt;

&lt;p&gt;But the deeper the accumulation, the more visible the cracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;My knowledge was locked in a local folder.&lt;/strong&gt; The classic scene: debugging a nasty issue at the office, I suddenly remember — I've hit this exact pit before, and the fix is written up in detail... in Obsidian, on my computer at home. End of story. I can't sync my entire vault onto every machine I touch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The graph is a beautiful lie.&lt;/strong&gt; Mention &lt;code&gt;[[some concept]]&lt;/code&gt; anywhere in a note and it enters the graph. A throwaway reference and a carefully built relationship get equal-weight edges. The more nodes, the prettier the graph — and the less it actually tells you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attachments scattered everywhere.&lt;/strong&gt; Architecture diagrams, flowcharts, PDFs spread across assets folders; move a folder and the links break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every sync option hurts somewhere.&lt;/strong&gt; Paid sync still needs a client installed; Syncthing can't go on a work machine; Git sync is technically possible and experientially miserable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I needed was simple: &lt;strong&gt;a web page. Log in, full editing, knowledge available anywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  UnDercontrol: make knowledge callable (Compound)
&lt;/h3&gt;

&lt;p&gt;No tool on the market was shaped quite like what I wanted, so I decided to build one. It's also an experiment: how far can one person, plus AI, take a product?&lt;/p&gt;

&lt;p&gt;UnDercontrol is my answer to every crack from the first two eras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Available anywhere&lt;/strong&gt;: log in from any browser; plus a CLI and a desktop app, with &lt;code&gt;ud pull / ud push&lt;/code&gt; syncing tasks to local Markdown files bidirectionally — the convenience of the web &lt;em&gt;and&lt;/em&gt; the reassurance of local files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Links I build explicitly&lt;/strong&gt;: only deliberately created relationships (peer / parent-child) enter the knowledge graph. Every edge means something. High signal, low noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized resources&lt;/strong&gt;: images, PDFs, and attachments stay attached to their context, but you can browse, search, and reuse them all in one unified library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not just tasks&lt;/strong&gt;: UnDercontrol's Markdown editor is shared across every text surface — tasks, notes, finance records, documents, all the same editing experience. A task can be a document, a decision record, a blog draft.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-native&lt;/strong&gt;: the knowledge base is open to AI. Claude Code, Codex, OpenCode, or any terminal-based agent can read and write the same knowledge through the CLI. In fact, the post you're reading right now was written by an AI agent inside an UnDercontrol task, drawing on my past notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the third stage of compounding: knowledge is no longer just &lt;em&gt;stored&lt;/em&gt; or &lt;em&gt;connected&lt;/em&gt; — it can be &lt;strong&gt;called&lt;/strong&gt;. By future me, and by the AI working on my behalf.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time compounds into strength
&lt;/h3&gt;

&lt;p&gt;From architectural drawings to code, from China to Singapore, from Joplin to Obsidian to building my own tool — the career changed, the city changed, the software changed. The habit didn't: &lt;strong&gt;write down what you figured out today&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The essence of compounding isn't the rate of return. It's not stopping. The point of a tool is to make "not stopping" easy enough.&lt;/p&gt;

&lt;p&gt;For me, UnDercontrol is both a product and the container for that habit. I use it every day to manage my tasks, notes, and finances — and to manage the building of UnDercontrol itself. I grow with it, and it remembers everything that time has laid down.&lt;/p&gt;

&lt;p&gt;If you've migrated through Joplin, Obsidian, and a dozen other tools — if you also believe knowledge compounds — come try &lt;a href="https://oatnil.com" rel="noopener noreferrer"&gt;UnDercontrol&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>markdown</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Why Your Board Won't Show What You Actually Care About</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Thu, 16 Jul 2026 09:50:57 +0000</pubDate>
      <link>https://dev.to/oatnil/why-your-board-wont-show-what-you-actually-care-about-6g9</link>
      <guid>https://dev.to/oatnil/why-your-board-wont-show-what-you-actually-care-about-6g9</guid>
      <description>&lt;p&gt;Monday morning, you open the board. What you want to know is what's about to blow up: what's already overdue, what's due this week. The board only tells you what's In Progress.&lt;/p&gt;

&lt;p&gt;There's a lot it won't show you. You want to see work by client, by sprint, by document type — there's no option for that. You want to pull the unassigned tasks into their own column — also no. You want one column watching overdue items, one watching this week's urgent ones, one just holding whatever was touched most recently, all mixed together — can't do it. The only things you can really change are the column names and their order.&lt;/p&gt;

&lt;p&gt;So the board shows you the tool's idea of your work, not yours. The dimensions you care about, it can't hold a single one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mrno1t53ebcfevu691e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2mrno1t53ebcfevu691e.png" alt="On the left, the three-column board every tool hands you, which can't hold the dimensions you care about; on the right, the board you described in one sentence and an agent built to fit" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why most tools work this way
&lt;/h3&gt;

&lt;p&gt;This isn't one tool's problem. Switch to another and you'll probably still get Todo, In Progress, Done. Most tools look alike because they share an assumption underneath: &lt;strong&gt;a column isn't something you define — it is the status enum, hardwired.&lt;/strong&gt; What you drag a card into is an enum value, not a viewpoint you decide.&lt;/p&gt;

&lt;p&gt;Tools have a reason for this. Flexibility usually costs you tuition. A tool that lets a column be anything tends to hand you a query language, a docs site, and a weekend along with it. Most people don't want to pay that, which is fair, so the tool decides for you: three columns, don't overthink it.&lt;/p&gt;

&lt;p&gt;UnDercontrol takes a different route. It's a task and knowledge management tool where the day-to-day operations can be handled by an AI agent in your terminal and a command line. On a board, that means a column is no longer equal to a status — it's a condition: what kind of task belongs here. Status is just one condition among many, with no special standing. You can split by due date, by person, by tag, by your own custom field, because to the system these are all the same thing.&lt;/p&gt;

&lt;p&gt;As for that tuition, we'll get to how it's waived.&lt;/p&gt;

&lt;h3&gt;
  
  
  Even the out-of-the-box board isn't only statuses
&lt;/h3&gt;

&lt;p&gt;That sounds like a promise until you see it. Create a new board and two of the six default columns aren't statuses at all:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;To Do&lt;/td&gt;
&lt;td&gt;Todo tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In Progress&lt;/td&gt;
&lt;td&gt;In-progress tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Done&lt;/td&gt;
&lt;td&gt;Done tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;Archived tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recent Created&lt;/td&gt;
&lt;td&gt;The most recently created, whatever the status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recent Updated&lt;/td&gt;
&lt;td&gt;The most recently touched, whatever the status&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The last two have no filter at all — they just sort by time, newest first. They don't belong to any status. They're a viewpoint.&lt;/p&gt;

&lt;p&gt;In a tool where a column equals a status, columns like those are hard to express. Here they're unremarkable, part of the default setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-35d77f83ee8a41798bb4b2e1831ac70a.r2.dev%2Ffeatures%2Fblog%2Fkanban-boards%2Fdefault-board.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpub-35d77f83ee8a41798bb4b2e1831ac70a.r2.dev%2Ffeatures%2Fblog%2Fkanban-boards%2Fdefault-board.png" alt="The six default columns; the rightmost two, Recent Created and Recent Updated, sort only by time and belong to no status" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So what about the tuition?
&lt;/h3&gt;

&lt;p&gt;If it's this flexible, doesn't that mean I have to learn a syntax before I can assemble the board I want?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No. You just say what you want.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You: build me a board that tracks deadlines — overdue, this week, next week, and no deadline set. Four columns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it. Claude Code, Codex, OpenCode, or any agent running in your terminal takes it from there. What the fields are called, how the conditions are written, what the YAML looks like, which commands to run — all of that is its job.&lt;/p&gt;

&lt;p&gt;The query language does exist, and it's complete, but it isn't your homework. It's the agent's working language. You hire someone to renovate; you don't need to lay the bricks yourself.&lt;/p&gt;

&lt;p&gt;If you're curious, here's what it wrote for you, without you typing a character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Board&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deadline Radar&lt;/span&gt;
  &lt;span class="na"&gt;columns&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Overdue&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deadline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;now&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;AND&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;!=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'done'"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;This Week&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deadline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;BETWEEN&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;now&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;AND&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;+7d"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice if you can read it, and it makes no difference to your use if you can't. That's the point.&lt;/p&gt;

&lt;h4&gt;
  
  
  And you don't have to teach the agent either
&lt;/h4&gt;

&lt;p&gt;Normally, to get an agent to use some tool, you first write it a manual: how to call it, what the fields are named, what the format is. You teach it once, the tool ships an update, the manual goes stale, and the agent starts making things up.&lt;/p&gt;

&lt;p&gt;UnDercontrol's command line ships with a recipe catalog. The agent doesn't read source and you don't feed it docs — it asks &lt;code&gt;ud cook board&lt;/code&gt; and the tool tells it how to build a board, complete with a runnable example. Its whole learning step is one command. The tool knows how to use itself, so you neither learn it nor teach it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drag a card in, and the board makes it true
&lt;/h3&gt;

&lt;p&gt;There's another half to the flexibility: how these columns respond to a drag is something no one has to configure.&lt;/p&gt;

&lt;p&gt;The logic is plain. A column says it holds in-progress tasks. Drop a card into it, and the only reasonable meaning is to make that true, so the status flips to in-progress on its own. Another column says it holds cards tagged blog; drop one in and the tag is added, drag it out and the tag comes off.&lt;/p&gt;

&lt;p&gt;You only said what each column holds; how to do it, the system works out itself. There's a quiet benefit to that: a column's description and its behavior can't drift apart, because the second is derived from the first — there's no second copy of the config to go wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  It knows when not to act
&lt;/h3&gt;

&lt;p&gt;Say a column is for what's already overdue. You drop a card into it — should the system change the deadline to yesterday?&lt;/p&gt;

&lt;p&gt;That's a guess. It's probably not what you meant; you may have just dropped it in the wrong place. So it does nothing. Any condition that can't be satisfied by one honest write — time ranges, sorting, fuzzy matching — generates no action at all. Those columns become views you look at, and you can't break them by dragging.&lt;/p&gt;

&lt;p&gt;Here's the real output, a four-column deadline radar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Columns:
    1. Overdue
       query: deadline &amp;lt; now AND status != 'done'
    2. This Week
       query: deadline BETWEEN now AND +7d
    3. Recently Touched
       query: ORDER BY updated_at DESC
    4. Urgent
       query: tags CONTAINS 'urgent'
       on enter: ADD tags 'urgent'  (auto)
       on exit: REMOVE tags 'urgent'  (auto)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first three — overdue, this week, recently touched — have no actions at all; they're read-only views. The fourth, Urgent, is defined by a tag, which one write can satisfy, so dropping a card in adds the tag and dragging it out removes it, all marked &lt;code&gt;(auto)&lt;/code&gt;, none of it configured by hand.&lt;/p&gt;

&lt;p&gt;The system won't invent a write it can't account for. That restraint isn't a shortfall in capability; it's exactly what lets "a column can be anything" be handed to you safely.&lt;/p&gt;

&lt;h3&gt;
  
  
  You see the real thing before it exists
&lt;/h3&gt;

&lt;p&gt;Handing board-building to an agent, the natural worry is what happens if it gets it wrong and makes a mess of your workspace.&lt;/p&gt;

&lt;p&gt;It won't, because there's a gate in the middle. The agent runs a preview first: the system renders the board exactly as it would be created — what each column holds, what a drag would do, all laid out — and then stores nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dry run — board would be created (nothing persisted):
  Name:  Blog Pipeline
  Type:  shared  (a group "Board: Blog Pipeline" would be created for sharing)
  Default tags: blog
  Columns:
    1. Idea
       query: status = 'todo' AND tags CONTAINS 'blog'
       on enter: SET status = 'todo'  (auto)
       on enter: ADD tags 'blog'  (auto)
       on exit: REMOVE tags 'blog'  (auto)
    2. Drafting
       query: status = 'in-progress' AND tags CONTAINS 'blog'
       on enter: SET status = 'in-progress'  (auto)
       ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;nothing persisted&lt;/code&gt;. At this point nothing has happened yet.&lt;/p&gt;

&lt;p&gt;So the whole thing becomes: you describe it, the agent previews it, you look at the real result, and if it's off you say change the review column to pending, it previews again, you nod, it lands.&lt;/p&gt;

&lt;p&gt;The key is that &lt;strong&gt;you're reviewing the system's output, not the agent's account of its plan&lt;/strong&gt;. The agent can say the wrong thing, but it can't fake this step's output. So the trust here isn't built on the agent never being wrong — it's that being wrong is fine, because you see it first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwp9bmhvzjgqdcgc65z7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwp9bmhvzjgqdcgc65z7b.png" alt="The deadline radar board an agent built — overdue, this week, and next week grouped by time window, cards showing due dates and assignees" width="800" height="811"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where this shows up
&lt;/h3&gt;

&lt;p&gt;Enough mechanism. Here's where it actually lives.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Monday-morning deadline radar
&lt;/h4&gt;

&lt;p&gt;You've got seven or eight things going at once, and on Monday morning there's only one thing you want to know: what's about to blow up.&lt;/p&gt;

&lt;p&gt;Tell an agent to build a board that tracks deadlines — overdue, this week, next week, no deadline set — and the four columns are there. Every Monday after that, whether the overdue column has anything in it is a glance.&lt;/p&gt;

&lt;p&gt;This board has a reassuring property too: those columns are computed from time, so you can't break them. If you fumble a card into Overdue, the system won't take it upon itself to change your deadline to yesterday — it does nothing. Columns like these are made to be looked at.&lt;/p&gt;

&lt;h4&gt;
  
  
  A team workload view
&lt;/h4&gt;

&lt;p&gt;Anyone running a team has had the question: who's buried, and who's actually free?&lt;/p&gt;

&lt;p&gt;A board with one column per teammate answers it, with a last column for the unassigned. Open it at standup and whose column is stacked, which work is still hanging, you can see without asking.&lt;/p&gt;

&lt;p&gt;A board like this is for looking. It flattens work scattered everywhere onto one screen. When you actually need to change who does what, you go back to the task itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  A content pipeline
&lt;/h4&gt;

&lt;p&gt;Blogging, videos, announcements — underneath they're the same pipeline: idea, drafting, review, published.&lt;/p&gt;

&lt;p&gt;This is a board you drag on. Move a card from Drafting to Review and the status follows, the tag is added, because each column has stated what it holds and the system derives the rest. You just drag; it makes what you said come true.&lt;/p&gt;

&lt;h4&gt;
  
  
  The plan changed, so say one more sentence
&lt;/h4&gt;

&lt;p&gt;Two weeks in, you notice there's no home for archived items. Tell an agent to add an archived column; it takes the board's full current state, previews the change for you, and only lands it once you nod.&lt;/p&gt;

&lt;p&gt;In another tool, changing a board means clicking through it again. Here it's a sentence, and getting it wrong doesn't matter, because you saw it before it took effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Once it's built, it's still yours
&lt;/h3&gt;

&lt;p&gt;That "add an archived column" works because the board isn't a trail left by clicks — it's something you can lift out whole.&lt;/p&gt;

&lt;p&gt;Export it, edit it, put it back — all fine. That's also why the agent never has to guess when it changes the board: it gets the full current state, not a reconstruction from the UI.&lt;/p&gt;

&lt;p&gt;A side benefit: the board can go into git, be handed to a colleague, be copied to another project. It's an asset of yours, not config locked inside some screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your board, your design, none of the homework
&lt;/h3&gt;

&lt;p&gt;Boards all look alike because the tool made the trade-off for you: simple but dumb, or powerful but you have to learn it.&lt;/p&gt;

&lt;p&gt;UnDercontrol's answer is that you decide what you want, the agent handles how, and the system keeps it from doing the wrong thing.&lt;/p&gt;

&lt;p&gt;So the four-column deadline radar, the by-person team view, the board sliced along your own business dimension — none of these are features someone designed ahead of time. They're just the result of a sentence you said.&lt;/p&gt;

&lt;p&gt;If you want to try it, describe the board you want to your agent. It knows what to do from there.&lt;/p&gt;

</description>
      <category>kanban</category>
      <category>productivity</category>
      <category>ai</category>
      <category>devtools</category>
    </item>
    <item>
      <title>AI Doesn't Just Work Inside UnDercontrol — It Runs UnDercontrol Itself</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Tue, 14 Jul 2026 11:24:55 +0000</pubDate>
      <link>https://dev.to/oatnil/ai-doesnt-just-work-inside-undercontrol-it-runs-undercontrol-itself-5e8m</link>
      <guid>https://dev.to/oatnil/ai-doesnt-just-work-inside-undercontrol-it-runs-undercontrol-itself-5e8m</guid>
      <description>&lt;p&gt;The "agent workbench" idea is heating up. More and more people agree: an AI agent should act like a teammate — pick up tasks, report progress, leave durable output — not just answer questions in a chat box.&lt;/p&gt;

&lt;p&gt;But there's a further question that rarely gets asked: &lt;strong&gt;can the AI operate the platform itself?&lt;/strong&gt; Not just do work inside the system, but &lt;em&gt;run&lt;/em&gt; it for you — tidy up boards, archive stale tasks, maintain tags, distill hard-won steps into a reusable capability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rbbgc1nt0lyxzjduvm0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rbbgc1nt0lyxzjduvm0.png" alt="Not just a worker — an operator of the platform itself" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UnDercontrol's answer comes from its core idea: &lt;strong&gt;Everything as Code&lt;/strong&gt;. Because of it, AI here is both a teammate that does the work and an admin that keeps the system in order.&lt;/p&gt;

&lt;h3&gt;
  
  
  The core: Everything as Code — the platform is the AI's control surface
&lt;/h3&gt;

&lt;p&gt;In UnDercontrol, tasks, notes, boards, skills, custom fields — &lt;strong&gt;all of it is plain Markdown + YAML frontmatter&lt;/strong&gt;, managed declaratively through one kubectl-style &lt;code&gt;ud&lt;/code&gt; CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Creating or updating a task is just applying some text&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' | ud apply -f -
---
title: Ship v1
status: in-progress
tags: [release, urgent]
metadata:
  priority: high
---
Pre-release checklist…
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fioft4l3s00ejqy87roac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fioft4l3s00ejqy87roac.png" alt="Everything as Code — tasks, boards, skills, metadata are all Markdown + one CLI" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the key: &lt;strong&gt;the same abilities an AI agent uses to read and write code — run commands, read and write text — work unchanged on the whole platform.&lt;/strong&gt; It can create tasks, break out subtasks, change statuses, apply tags, build boards (a board is just a saved query), distill a repeated prompt into a new Skill, patch custom fields… Those management actions are themselves code.&lt;/p&gt;

&lt;p&gt;In short: the AI isn't only a &lt;strong&gt;worker&lt;/strong&gt; inside the platform — it can also be an &lt;strong&gt;admin&lt;/strong&gt;, because managing the platform is itself programmable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft1g0hooibn27ukvg2i37.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft1g0hooibn27ukvg2i37.png" alt="An Engineering board — columns are saved queries the agent can build and reshape" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical scenarios&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Archive everything marked done this week, then spin up a new board filtered by the &lt;code&gt;release&lt;/code&gt; tag" — the agent just does it with &lt;code&gt;ud apply&lt;/code&gt; / &lt;code&gt;ud patch&lt;/code&gt;, no clicking around.&lt;/li&gt;
&lt;li&gt;"Save the debugging steps you just walked through as a Skill" — the agent turns the method from the conversation into a reusable Skill with &lt;code&gt;ud apply&lt;/code&gt;, and the whole team can use it next time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Breaking it down: the UnDercontrol agent workbench
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Agents as teammates.&lt;/strong&gt; Write a requirement as a task, @mention an agent, and it claims the task, reads the description, notes, and links as context, writes code, runs tests, commits, and writes progress back into the notes. What it picks up isn't a black-box issue — it's &lt;strong&gt;structured Markdown it can also edit itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hcnmq29tr2enq3x6bqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hcnmq29tr2enq3x6bqt.png" alt="Task detail — the agent reads the description and writes progress + commits back into the notes timeline" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Daemon / runtime.&lt;/strong&gt; The agent runs on your own dev machine — a background &lt;strong&gt;daemon&lt;/strong&gt; stays connected over SSE and streams the terminal output back in real time. This remote workspace has been in the works since April 2026; today daemon registration, SSE, multi-surface triggering, and session viewing are all in place — you can start and monitor from the web, the desktop app, the CLI, even your phone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reusable skills.&lt;/strong&gt; A Skill is a reusable prompt template stored on the server and injected into any agent via &lt;code&gt;ud prompt&lt;/code&gt;. And because everything is code, &lt;strong&gt;an agent can write and revise Skills itself with &lt;code&gt;ud apply&lt;/code&gt;&lt;/strong&gt; — the skill library is a programmable asset that compounds over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not tied to any one agent.&lt;/strong&gt; UnDercontrol is agent-agnostic: an Agent CLI command template plugs in Claude Code, Codex, Cursor, Hermes, or any terminal-based agent. Swap models or tools without swapping workbenches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You own your data.&lt;/strong&gt; Tasks and notes are plain Markdown files with YAML frontmatter, defined by an open &lt;a href="https://github.com/oatnil-top/ud-schemas" rel="noopener noreferrer"&gt;JSON Schema&lt;/a&gt; (MIT) — version them with Git, export anytime, and self-host (Docker Compose / K8s, SQLite / Postgres).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Not just tasks&lt;/strong&gt;: this Markdown editor and the everything-as-code foundation run through every surface of UnDercontrol — tasks, notes, even expenses and resources. The agent workbench isn't a separate module; it's a capability that grows out of that foundation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why "AI can operate the platform itself" matters
&lt;/h3&gt;

&lt;p&gt;In most tools, AI handles the &lt;strong&gt;execution layer&lt;/strong&gt; (write code, run tests), while the &lt;strong&gt;management layer&lt;/strong&gt; — tidying boards, archiving old tasks, maintaining a tag system, distilling experience into SOPs — still sits on humans.&lt;/p&gt;

&lt;p&gt;When the platform itself is code, that line disappears: AI can share both execution and management. Your knowledge base is both &lt;strong&gt;content&lt;/strong&gt; and a &lt;strong&gt;programmable control surface&lt;/strong&gt;. You gain a teammate who does the work — and an admin who keeps the system in order.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdqjrc7bqbsb8w83m2ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqdqjrc7bqbsb8w83m2ri.png" alt="Most tools stop at execution; here AI shares the management layer too" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping up
&lt;/h3&gt;

&lt;p&gt;The heart of an "agent workbench" is letting AI do the work reliably, leave durable output, and be directed. UnDercontrol goes one step further — via &lt;strong&gt;Everything as Code&lt;/strong&gt;, it lets AI operate the platform itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks, boards, skills, and metadata are all plain Markdown + CLI-manageable code;&lt;/li&gt;
&lt;li&gt;so the same agent can both &lt;strong&gt;work inside the platform&lt;/strong&gt; (write code, report progress) and &lt;strong&gt;operate the platform itself&lt;/strong&gt; (build boards, archive, write Skills, maintain structure);&lt;/li&gt;
&lt;li&gt;all of it agent-agnostic, triggerable from any device, with your data your own.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In UnDercontrol, AI is both a teammate and an admin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgn0tj0v8sx26xrg5i0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmgn0tj0v8sx26xrg5i0w.png" alt="Everything as Code — so AI can run the platform, not just work in it" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>programming</category>
    </item>
    <item>
      <title>One Board, the Whole Project in View — A Week with Kanban</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Mon, 13 Jul 2026 04:52:37 +0000</pubDate>
      <link>https://dev.to/oatnil/one-board-the-whole-project-in-view-a-week-with-kanban-4883</link>
      <guid>https://dev.to/oatnil/one-board-the-whole-project-in-view-a-week-with-kanban-4883</guid>
      <description>&lt;p&gt;Monday, 9 a.m. You open UnDercontrol, glance at one board, and already know where this week starts.&lt;/p&gt;

&lt;p&gt;This is your side project &lt;strong&gt;MorningRun&lt;/strong&gt; — a running social app, currently in Sprint 12. Five columns line up across the board: Todo, In Progress, Review, Deployed, Done. What hasn't started, what's stuck, what's waiting on someone else — you can see it all without opening a single task. Let's walk through a whole week with this one board.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v09dxzhg3c5jslklyn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v09dxzhg3c5jslklyn4.png" alt="One board, the whole project in view — drag a card, the status updates itself" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Monday: drag from "Todo" to "In Progress"
&lt;/h3&gt;

&lt;p&gt;You grab a card — "Implement Google OAuth login" — and drag it from &lt;strong&gt;Todo&lt;/strong&gt; to &lt;strong&gt;In Progress&lt;/strong&gt;. The moment you let go, the task's status flips to "In Progress" on its own. No dropdown, no form.&lt;/p&gt;

&lt;p&gt;That's the heart of kanban in UnDercontrol: &lt;strong&gt;columns are the stages of your workflow, and dragging is the status change&lt;/strong&gt;. Whichever column a card lands in, the task's status, tags, even custom fields update to match. And it's instant — the same task in your task list is already in sync.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8dhw3813dxcxla779ctc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8dhw3813dxcxla779ctc.png" alt="Sprint 12 board overview — Todo / In Progress / Review / Deployed / Done" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tuesday: a card is more than a title
&lt;/h3&gt;

&lt;p&gt;You open that OAuth card. Inside isn't a single dry line — it's a full Markdown document: a requirements checklist, the technical approach, a couple of open questions. This is the task's living document, its single source of truth.&lt;/p&gt;

&lt;p&gt;Below it you append a &lt;strong&gt;note&lt;/strong&gt;: "Callback URL verified on the staging redirect — commit a1b2c3d." Notes are an append-only timeline that records how the work progressed, and each one keeps a full edit history you can roll back to anytime.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Not just tasks&lt;/strong&gt;: UnDercontrol's editor is shared across every text surface. Task bodies, notes, expense memos, account notes — whatever you write, it's the same Markdown experience. Every card on the board is backed by a container that holds the complete picture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zzf799jzu0udi13946o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zzf799jzu0udi13946o.png" alt="Card detail — Markdown body (requirements, open questions) and the notes timeline on the right" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wednesday: customize a column, let the board do the chores
&lt;/h3&gt;

&lt;p&gt;The default columns are status-based. But your team added a code-review step, so you &lt;strong&gt;customize a column&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Open "Edit Column" and you only fill in three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Column name&lt;/strong&gt;: Review&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match condition&lt;/strong&gt;: &lt;code&gt;status = 'pending' AND tags CONTAINS 'needs-review'&lt;/code&gt; — which cards land here&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic action&lt;/strong&gt;: when a card enters this column, auto-add the &lt;code&gt;needs-review&lt;/code&gt; tag and @-mention your teammate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when you drag the OAuth card into "Review," a few things happen on their own: the tag is added, your teammate gets pinged. &lt;strong&gt;A column's automatic actions are generated from its match condition&lt;/strong&gt;, always in sync; for anything fancier you can add actions manually.&lt;/p&gt;

&lt;p&gt;A few minutes later your teammate leaves a &lt;strong&gt;comment&lt;/strong&gt; on the card: "The callback URL is missing the staging domain in the allow-list." You reply: "Good catch — added it 👍." Comments are a lightweight, threaded discussion — short and focused, back and forth, without switching to IM and without drowning in the body text. The body says "what it is," notes record "how it evolved," and comments are "let's quickly align on this one card."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1pxauwe9xz6p0xjuyzmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1pxauwe9xz6p0xjuyzmh.png" alt="The comment thread on the card — teammate flags the callback URL, you confirm the fix" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One column isn't enough. You add a second custom column, &lt;strong&gt;"Deployed"&lt;/strong&gt;: match condition &lt;code&gt;status = 'pending' AND tags CONTAINS 'deployed'&lt;/code&gt;, and on enter it sets the status to &lt;code&gt;done&lt;/code&gt;. Two custom columns later, the flow from review to shipped runs right on the board.&lt;/p&gt;

&lt;p&gt;This is where kanban gets genuinely powerful — it doesn't just show, it works for you. Drag a card once, and all the status changes, tagging, and notifications happen in one move.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F410sebv28c5gh38b9ulz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F410sebv28c5gh38b9ulz.png" alt="Edit Column dialog — name, match conditions, and the auto-generated query and actions" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Thursday: columns don't have to be statuses
&lt;/h3&gt;

&lt;p&gt;Midweek, you realize status columns aren't enough. MorningRun ships next week, and what you really care about is "what must get done this week." So you spin up another board — "Release Sprint" — where the columns aren't Todo / Done but &lt;strong&gt;This Week / Next Week / Backlog&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because behind every column is a query condition. "This Week" filters &lt;code&gt;deadline &amp;lt;= this Sunday&lt;/code&gt;; "Backlog" filters &lt;code&gt;status = 'todo' AND deadline IS NULL&lt;/code&gt;. A board is essentially &lt;strong&gt;a saved query&lt;/strong&gt;, not a folder that holds things — so the same task can appear on both "Sprint 12" and "Release Sprint" with zero duplication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical scenarios&lt;/strong&gt;: one board to push daily development by status; another to plan priorities by time; a separate one per client project. Same set of tasks, several angles, each its own view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0y5v7e3q94jnisbb5qbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0y5v7e3q94jnisbb5qbi.png" alt="Release Sprint board — columns become This Week / Next Week / Backlog, the same cards from another angle" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Friday: share the board with your team
&lt;/h3&gt;

&lt;p&gt;MorningRun's designer is taking over the UI cards this week. You open the board settings, click "Share," and pick your team group. She sees the board immediately — but &lt;strong&gt;only the tasks that belong to that group&lt;/strong&gt;; your own private tasks stay hidden. Who's read-only and who can move cards is controlled by permissions.&lt;/p&gt;

&lt;p&gt;No extra sync meeting, no "where are we at?" pings. A shared board is where the team stays aligned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswjzops81ucbzojkdped.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswjzops81ucbzojkdped.png" alt="Share the board with your team group — members see only group tasks, with read/write permissions" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The week, in summary
&lt;/h3&gt;

&lt;p&gt;This week you didn't hold a single "sync meeting" and didn't bounce between apps. One board showed you the whole MorningRun project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drag = status change&lt;/strong&gt; — columns are workflow stages, drop to update, synced instantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A card is a complete information container&lt;/strong&gt; — Markdown body + notes timeline + comments behind every card&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom columns do the chores&lt;/strong&gt; — auto-update status, tag, and notify from a match condition; two columns wired up the review-to-shipped flow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Columns don't have to be statuses&lt;/strong&gt; — This Week / Next Week / Backlog; a board is a saved query, not a folder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A shared board = team alignment&lt;/strong&gt; — only group tasks show, permissions controlled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Want to try it? Open UnDercontrol and drag your first card — and watch the status change itself.&lt;/p&gt;

</description>
      <category>kanban</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>projectmanagement</category>
    </item>
    <item>
      <title>At 1 A.M., an AI Writes Blog Posts Inside My Task System</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sun, 12 Jul 2026 02:23:39 +0000</pubDate>
      <link>https://dev.to/oatnil/at-1-am-an-ai-writes-blog-posts-inside-my-task-system-5f8i</link>
      <guid>https://dev.to/oatnil/at-1-am-an-ai-writes-blog-posts-inside-my-task-system-5f8i</guid>
      <description>&lt;p&gt;At eight in the morning, coffee in hand, I open my kanban board. Sitting in the Pending column is a new task:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2026-07-12 Blog Draft (scheduled)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside it: a complete blog draft. And in the comment thread, two messages left overnight:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;01:01&lt;/strong&gt; — On it — topic scan done, picking task-management-overview. Drafting now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;01:03&lt;/strong&gt; — Done — draft is in the note. Task set to pending for review.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The author is not a person. It's an AI agent. While I was asleep, it picked a topic, checked the product docs, wrote the draft, moved the task to "pending review", and said hi in the comment thread.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa4jccz0vt09mrpfnlxt6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa4jccz0vt09mrpfnlxt6.png" alt="Kanban board with the blog draft task sitting in the Pending Review column" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I read the draft and replied with one line: "Too broad. Find one concrete use case and tell it as a story." A few minutes later, the draft had been rewritten — the post you are reading now is the product of that rewrite.&lt;/p&gt;

&lt;p&gt;This post is about how that pipeline is built, and why a task system is the most comfortable handoff point between humans and AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  A task is not just a to-do item
&lt;/h3&gt;

&lt;p&gt;First, a core design idea: in UnDercontrol, &lt;strong&gt;a task is a universal information container&lt;/strong&gt;, not just a to-do.&lt;/p&gt;

&lt;p&gt;A task can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An actual to-do ("fix the validation bug on the login page")&lt;/li&gt;
&lt;li&gt;A document (a design proposal, meeting minutes, a wiki page)&lt;/li&gt;
&lt;li&gt;A decision record (why we chose option B)&lt;/li&gt;
&lt;li&gt;A blog draft (this post's draft lives as a note on a task)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The task body is Markdown. Combined with tags and custom metadata, you decide what a task &lt;em&gt;is&lt;/em&gt; — instead of being boxed in by the tool's data structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem: I want a steady blog, without starting from zero every day
&lt;/h3&gt;

&lt;p&gt;Anyone building a product knows this: content needs to ship consistently, but the activation energy of writing is brutal. Picking a topic, gathering material, structuring, drafting — every step burns energy that should have gone into code.&lt;/p&gt;

&lt;p&gt;Let the AI write and publish fully automatically? No. Content that ships without a human gatekeeper burns your own reputation.&lt;/p&gt;

&lt;p&gt;What I wanted was a &lt;strong&gt;human–AI pipeline&lt;/strong&gt;: the AI does the grunt work (topic dedup, doc research, first draft), and I only do the one step that's actually worth my time — judgment and feedback.&lt;/p&gt;

&lt;p&gt;So the question becomes: &lt;strong&gt;where does the AI's work go? Where do I review it? How does feedback flow back?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer: all of it lives in the task system.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pipeline: 24 hours in the life of one task
&lt;/h3&gt;

&lt;p&gt;There is no dedicated "AI platform" here. The pipeline is assembled from four native capabilities of the task system: scheduled jobs, @mentions, notes, and comments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frq1sdotm5flhrgpgihrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frq1sdotm5flhrgpgihrt.png" alt="The 24-hour handoff loop: scheduled job creates the task, mention wakes the agent, draft lands as a note, human reviews in the morning" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;01:00 — The scheduled job fires&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A daily scheduled job (CRON) creates the day's draft task. The task description is the complete instruction set for the AI, and it opens by @mentioning my agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;@ud-agent&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;mention://member/...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

Generate ONE blog DRAFT for review — do NOT run the full publish pipeline.
&lt;span class="p"&gt;
1.&lt;/span&gt; Pick a topic from &lt;span class="sb"&gt;`auto/blog-topics.json`&lt;/span&gt;. Skip topics already covered —
   check with &lt;span class="sb"&gt;`ud grep task "&amp;lt;slug&amp;gt;"`&lt;/span&gt;. Choose the first uncovered topic.
&lt;span class="p"&gt;2.&lt;/span&gt; Write ONLY the text draft as a NOTE on THIS task.
&lt;span class="p"&gt;3.&lt;/span&gt; Set THIS task status to &lt;span class="sb"&gt;`pending`&lt;/span&gt; and reply in the comment thread.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the design here: &lt;strong&gt;the task description is the prompt&lt;/strong&gt;. Instructions, boundaries ("do NOT publish"), acceptance criteria ("set to pending") — all written into the task. No separate configuration system needed. The task &lt;em&gt;is&lt;/em&gt; the config.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmqtuup3e2pox5jtr9af5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmqtuup3e2pox5jtr9af5.png" alt="Scheduled Jobs page showing the daily 01:00 blog-draft job" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;01:01 — The @mention wakes the agent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The mention triggers an agent work session. It wakes up on my Mac, and the first thing it does is not writing — it's detective work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the topic list (a JSON file in the repo, 18 candidate topics)&lt;/li&gt;
&lt;li&gt;Search old tasks with &lt;code&gt;ud grep task&lt;/code&gt; and &lt;code&gt;ud query "tags CONTAINS 'blog'"&lt;/code&gt; to see which topics are already covered&lt;/li&gt;
&lt;li&gt;Sweep 27 historical blog tasks, find only 2 topics left uncovered — pick the first one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it leaves its first message in the comment thread ("On it — picking task-management-overview") before writing a word. It also reads the product docs to verify feature details first — an AI's worst habit is confidently making things up, and making it read the docs first cures most of that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;01:03 — The draft lands, the task flips to pending&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The finished draft doesn't go to some "AI output panel" — it's attached to the task as a &lt;strong&gt;note&lt;/strong&gt;. The task status is set to &lt;code&gt;pending&lt;/code&gt;, which in our status model means "I'm done, waiting on someone else." The agent leaves a second message in the thread and clocks out.&lt;/p&gt;

&lt;p&gt;The whole run took two minutes, and it happened after I fell asleep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;08:00 — I come online, and only judge&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My review interface is just the task detail page: the draft in a note, the context in the description, the agent's work log in the comment thread. I don't need to open any other tool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F204bzycnbew5ut9yvcty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F204bzycnbew5ut9yvcty.png" alt="Task detail page: the scheduled prompt as description, the draft as a note below" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I read the draft and replied with one line in the thread. That line triggered a new agent session — it read the feedback, &lt;strong&gt;updated the same note via &lt;code&gt;note_id&lt;/code&gt;&lt;/strong&gt; (not a new note; notes keep full edit history, so a bad rewrite can always be rolled back), then replied in the thread describing what changed.&lt;/p&gt;

&lt;p&gt;Back and forth, it feels like collaborating with a remote teammate through a ticket. Except this teammate starts work at 1 A.M. and never complains about rework.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10xy1sqp6po992g3bat1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F10xy1sqp6po992g3bat1.png" alt="The comment thread: agent reports progress, human replies with one-line feedback, agent confirms the rewrite" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the handoff point is a task, not a chat window
&lt;/h3&gt;

&lt;p&gt;The biggest problem with collaborating with AI in a chat window is that &lt;strong&gt;output sinks&lt;/strong&gt;. What it wrote yesterday is fifty screens up today; switch sessions and the context is gone.&lt;/p&gt;

&lt;p&gt;Make the handoff point a task, and every part of the exchange gets a native container:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task description&lt;/strong&gt; = requirements and instructions (a living document, always current)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes&lt;/strong&gt; = deliverables and process records (an append-only timeline with edit history)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comments&lt;/strong&gt; = lightweight conversation (short, threaded, with @ notifications)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status&lt;/strong&gt; = position in the workflow (&lt;code&gt;pending&lt;/code&gt; means "awaiting review" — one glance at the board shows everything waiting on you)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And humans and AI access all of it through &lt;strong&gt;the same entrance&lt;/strong&gt;. I read on the web and my phone; the agent reads and writes from the terminal via the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ud describe task 51c4981e      &lt;span class="c"&gt;# read the task (notes, comments, attachments included)&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;draft.md | ud apply &lt;span class="nt"&gt;-f&lt;/span&gt; -   &lt;span class="c"&gt;# write a note&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the entrance is CLI + Markdown, the pipeline is not tied to any specific AI tool — Claude Code, Codex, OpenCode, or any terminal-based agent can plug in. Swap the agent tomorrow; the pipeline doesn't change by a single line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where else this pattern applies
&lt;/h3&gt;

&lt;p&gt;The blog draft is just the most convenient example. The same loop — "scheduled job / @mention → agent works → notes for the record → pending for review → feedback in comments" — also runs our:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Release verification&lt;/strong&gt;: after CI ships a version, a task is created with the release notes attached; the agent runs smoke tests and writes results into a note&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily standup&lt;/strong&gt;: a scheduled job creates a standup task every day; the agent summarizes yesterday's changes across all tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code research&lt;/strong&gt;: throw "evaluate option X" at the agent, wake up to a comparison in the notes, ask follow-ups in the comments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's only one common thread: &lt;strong&gt;every step of the AI's work stays in the task, and the human appears only at the checkpoints.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Takeaway
&lt;/h3&gt;

&lt;p&gt;This pipeline uses no concept invented specifically for AI. Scheduled jobs, @mentions, notes, comments, status — all of it is what a task system already has. It's just that when your task system meets three conditions, it naturally becomes a human–AI workbench:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Markdown-native&lt;/strong&gt; — AI reads and writes without a translation layer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A CLI entrance&lt;/strong&gt; — any terminal agent can plug in; no vendor lock-in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status + comments + notes, all first-class&lt;/strong&gt; — handoff, review, and records each have their place&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One more thing: this very post is what the pipeline produced in the small hours of July 12, 2026. The version you just read is the second draft — written after a human replied with a single line: "Too broad. Find one concrete use case and tell it as a story."&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>automation</category>
    </item>
    <item>
      <title>Turn Any Web Page into Clean Markdown for Your AI — UnDercontrol Web Clipper</title>
      <dc:creator>Oatnil</dc:creator>
      <pubDate>Sat, 11 Jul 2026 02:18:52 +0000</pubDate>
      <link>https://dev.to/oatnil/turn-any-web-page-into-clean-markdown-for-your-ai-undercontrol-web-clipper-13cd</link>
      <guid>https://dev.to/oatnil/turn-any-web-page-into-clean-markdown-for-your-ai-undercontrol-web-clipper-13cd</guid>
      <description>&lt;p&gt;You want to hand a web article to an AI — to summarize it, translate it, or ask questions about it. How do you do that today?&lt;/p&gt;

&lt;p&gt;Select-all and copy? You paste a mess of navigation bars, ads, recommendation widgets, and broken formatting. Send the link? Many AI tools can't fetch pages, and when they can, the result is often incomplete.&lt;/p&gt;

&lt;p&gt;The UnDercontrol &lt;strong&gt;Web Clipper&lt;/strong&gt; Chrome extension gives you a cleaner answer: click &lt;strong&gt;Copy Markdown&lt;/strong&gt;, and the page's article content is extracted into tidy Markdown on your clipboard — &lt;strong&gt;no login, no account, no configuration&lt;/strong&gt;. Install it and it works on any page. Paste it into Claude, ChatGPT, or any AI, and what it gets is pure content with zero noise.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy91gkoysvmq5wvtto8rk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy91gkoysvmq5wvtto8rk.png" alt="Web Clipper popup — Copy Markdown and Save to Local, no login required" width="640" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Copy Markdown: copy, redesigned for the AI era
&lt;/h2&gt;

&lt;p&gt;This is the extension's most-used feature, and it doesn't depend on an UnDercontrol server at all:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-click copy&lt;/strong&gt;: the page's article content lands on your clipboard as clean Markdown&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart extraction&lt;/strong&gt;: powered by Readability + Turndown — ads, navigation, sidebars, and other non-content elements are stripped automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero barrier&lt;/strong&gt;: no sign-up, no login; works instantly on any page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust&lt;/strong&gt;: heavy elements like video and canvas are skipped automatically, so complex pages won't drag your browser down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Markdown is an AI's native language — clean structure, no markup noise. For the same article, pasting Markdown instead of a raw select-all copy gets you noticeably better comprehension and answers, and saves tokens too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs88c5ziylep5sz4x8iqk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs88c5ziylep5sz4x8iqk.png" alt="Web page to clean Markdown to your AI — one click, no login" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Save to Local: archive without logging in
&lt;/h2&gt;

&lt;p&gt;Local save also works without any login. One click downloads two files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A complete HTML snapshot&lt;/strong&gt;: built on the open-source &lt;a href="https://github.com/gildas-lormeau/SingleFile" rel="noopener noreferrer"&gt;SingleFile&lt;/a&gt;, it inlines HTML, CSS, images, and fonts into a single self-contained file that opens offline, exactly as the page looked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The extracted Markdown&lt;/strong&gt;: the same clean article content that Copy Markdown produces&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Links rot and pages get redesigned, but a snapshot is forever the page as it was the moment you saved it. Archive articles, research material, and time-sensitive pages — no server required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Save to UnDercontrol: clipping joins your workflow
&lt;/h2&gt;

&lt;p&gt;If you use UnDercontrol (the extension connects via login or an API key — self-hosted instances work out of the box), clipping goes one step further: the page becomes a &lt;strong&gt;task&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2p7gaye4k5tns21jneef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2p7gaye4k5tns21jneef.png" alt="Web Clipper ready view — title prefilled, tags, Save Page" width="640" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Markdown content goes into the task description&lt;/strong&gt; — readable and editable right inside the task&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The HTML snapshot is attached&lt;/strong&gt; to the task, so you can always reconstruct the original page&lt;/li&gt;
&lt;li&gt;From there you get the full task toolkit: tags, kanban boards, links to other tasks, notes for your conclusions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI agents can reach it&lt;/strong&gt;: through the ud CLI, Claude Code, Codex, OpenCode, or any terminal-based AI agent can read the task — the description already contains ready-to-use Markdown, so the agent never needs to scrape the web page itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a task produced by a real clip: the description starts with the source URL, the body is the extracted Markdown, and the full HTML snapshot hangs off the attachments panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzf6f3z1h66eo89rijiu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzf6f3z1h66eo89rijiu2.png" alt="A clipped task — source URL and Markdown in the description, HTML snapshot attached" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In UnDercontrol, a task has never been just a to-do item — it's a universal information container. Web clipping is simply one more way for information to enter it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Bilibili video subtitles become transcripts
&lt;/h2&gt;

&lt;p&gt;Web Clipper also ships with &lt;strong&gt;Bilibili transcript extraction&lt;/strong&gt;: on a Bilibili video page, the extension detects the video and lights up a &lt;strong&gt;Save Transcript&lt;/strong&gt; button that turns CC or AI-generated subtitles into a formatted Markdown transcript — download it locally or save it as an UnDercontrol task. Finish a tech talk video, and the transcript is archived in one click; handing it to an AI for a summary is one more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4nu6d9fw6hqcpgm8mv19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4nu6d9fw6hqcpgm8mv19.png" alt="Bilibili video detected — Save Transcript in one click" width="640" height="906"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Typical scenarios
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Feed your AI&lt;/strong&gt;: copy a long article as Markdown and paste it into any AI to summarize, translate, or interrogate — far cleaner than pasting a link or a raw copy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read-later that actually happens&lt;/strong&gt;: clip a worthwhile article into a task with a deadline; write your action items into the task notes when you're done&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Competitive research&lt;/strong&gt;: clip competitors' pricing and feature pages into a research board — when they redesign next week, you still hold today's snapshot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bug evidence&lt;/strong&gt;: a third-party page misbehaves? Clip a full snapshot onto the bug task; even after the page recovers, the scene is preserved&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video study notes&lt;/strong&gt;: turn a Bilibili tech video's subtitles into a Markdown transcript — archive it or let an AI distill the key points&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install and configure
&lt;/h2&gt;

&lt;p&gt;Install from the &lt;a href="https://chromewebstore.google.com/detail/undercontrol-web-clipper/mckkbigikfkoeddpcbhdmpncoljoagog" rel="noopener noreferrer"&gt;Chrome Web Store&lt;/a&gt;. &lt;strong&gt;Copy Markdown and local save work immediately with zero configuration&lt;/strong&gt;; only "save as task" needs a connection to your UnDercontrol server — log in directly, or create an API key (starts with &lt;code&gt;ak_&lt;/code&gt;) under &lt;strong&gt;Settings → API Keys&lt;/strong&gt; in the web app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ficikv77ljv45y1q6x5nd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ficikv77ljv45y1q6x5nd.png" alt="Login to server — username/password or API key, only needed for saving as tasks" width="640" height="842"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Chrome internal pages (&lt;code&gt;chrome://&lt;/code&gt;, &lt;code&gt;chrome-extension://&lt;/code&gt;) cannot be captured&lt;/li&gt;
&lt;li&gt;Full snapshots of pages heavy with dynamic content can take up to 2 minutes&lt;/li&gt;
&lt;li&gt;A snapshot is a point-in-time copy — it won't change when the original page does (which is exactly the point)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Web Clipper browser extension itself is open source under AGPL-3.0: &lt;a href="https://github.com/oatnil-top/ud-chrome-extension" rel="noopener noreferrer"&gt;github.com/oatnil-top/ud-chrome-extension&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Without logging in, it's a clean "web page to Markdown + local archive" tool, born for feeding content to AI. Logged in, every clip lands in a task system with tags, kanban boards, and AI-agent access. Next time you want to hand a web page to an AI, try Copy Markdown first.&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>productivity</category>
      <category>devtools</category>
      <category>chrome</category>
    </item>
  </channel>
</rss>
