<?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: kohei_wada</title>
    <description>The latest articles on DEV Community by kohei_wada (@kohei_wada).</description>
    <link>https://dev.to/kohei_wada</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%2F3842490%2Fe6c74985-243e-4aa7-a203-9bd7c938c187.png</url>
      <title>DEV Community: kohei_wada</title>
      <link>https://dev.to/kohei_wada</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kohei_wada"/>
    <language>en</language>
    <item>
      <title>Building a CLI Task Manager That Solves the "When to Do It" Problem Taskwarrior Lacked</title>
      <dc:creator>kohei_wada</dc:creator>
      <pubDate>Mon, 12 Oct 2026 15:42:06 +0000</pubDate>
      <link>https://dev.to/kohei_wada/building-a-cli-task-manager-that-solves-the-when-to-do-it-problem-taskwarrior-lacked-581n</link>
      <guid>https://dev.to/kohei_wada/building-a-cli-task-manager-that-solves-the-when-to-do-it-problem-taskwarrior-lacked-581n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Taskdog&lt;/strong&gt; is a CLI/TUI task management tool that auto-generates schedules from task deadlines, estimated durations, and priorities — all while respecting a daily work-hour limit.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Kohei-Wada/taskdog" rel="noopener noreferrer"&gt;https://github.com/Kohei-Wada/taskdog&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/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzie7metdapgh5w1croo3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzie7metdapgh5w1croo3.gif" alt="Taskdog TUI Demo" width="599" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are mountains of task management tools out there. Todoist, Notion, Trello — all of them are great tools.&lt;/p&gt;

&lt;p&gt;But none of them fit my workflow.&lt;/p&gt;

&lt;p&gt;So I decided to build my own.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Tools I Tried Along the Way
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Taskwarrior
&lt;/h4&gt;

&lt;p&gt;The first tool I tried was Taskwarrior.&lt;/p&gt;

&lt;p&gt;Taskwarrior is a fantastic CLI task manager. It has over 15 years of history, is simple and fast, and highly customizable. I used it for a while.&lt;/p&gt;

&lt;p&gt;But there was one big complaint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No automatic schedule generation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can set a deadline and an estimated duration on a task, but figuring out "OK, so when do I actually do this?" is still up to you. Taskwarrior is great at prioritizing &lt;em&gt;what&lt;/em&gt; to do, but scheduling &lt;em&gt;when&lt;/em&gt; to do it seems to be out of scope.&lt;/p&gt;

&lt;p&gt;Manually deciding "what and how much to do today" every single morning was, frankly, a pain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Motion / Reclaim.ai
&lt;/h4&gt;

&lt;p&gt;Next I tried AI scheduling services.&lt;/p&gt;

&lt;p&gt;Motion and Reclaim.ai are built around the concept of "AI auto-schedules your day." That certainly sounded convenient.&lt;/p&gt;

&lt;p&gt;But a few things bothered me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$19–34/month is steep (over $200/year)&lt;/li&gt;
&lt;li&gt;Cloud-required (I don't want to hand my task data over to a third party)&lt;/li&gt;
&lt;li&gt;Black-box AI (you can't tell why it picked this schedule)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when told "the AI decided," I felt like I was being handed a schedule I couldn't really get behind.&lt;/p&gt;

&lt;h4&gt;
  
  
  Asana / Jira / ClickUp
&lt;/h4&gt;

&lt;p&gt;I also tried team-oriented tools.&lt;/p&gt;

&lt;p&gt;They have tons of features, but they're way too heavy for personal use. Parent-child tasks, subtasks, epics, stories...&lt;/p&gt;

&lt;p&gt;One person working solo doesn't need that kind of complex structure.&lt;/p&gt;

&lt;h4&gt;
  
  
  Notion
&lt;/h4&gt;

&lt;p&gt;I use Notion for organizing team docs at work. The page hierarchy and database features are excellent.&lt;/p&gt;

&lt;p&gt;But it didn't suit my workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Heavy — just to add a task I have to open a browser, wait for the page to load...&lt;/li&gt;
&lt;li&gt;Weak task management — you can fake it with databases, but in the end it's a general-purpose tool&lt;/li&gt;
&lt;li&gt;Automatic scheduling? — nope&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I Actually Wanted
&lt;/h3&gt;

&lt;p&gt;In the end, here's the kind of tool I wanted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lives entirely in the terminal&lt;/strong&gt; — opening a GUI is annoying. I want to bang things out on the command line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generates the schedule for me&lt;/strong&gt; — give it priority, deadline, and estimate, and have it tell me "do this today"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cloud dependency&lt;/strong&gt; — privacy first. Data stays local&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent algorithms&lt;/strong&gt; — not "the AI decided," but "this logic produced this result" — something explainable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I couldn't find any existing tool that ticked all those boxes, so I built one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Comparison with Existing Tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Taskdog&lt;/th&gt;
&lt;th&gt;Taskwarrior&lt;/th&gt;
&lt;th&gt;Motion/Reclaim&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auto schedule generation&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work-hour limit aware&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skips weekends/holidays&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fully local&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transparent algorithms&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$19–34/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI/TUI&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependencies&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Where Taskdog fits&lt;/strong&gt;: Taskwarrior's usability + Motion/Reclaim's automatic scheduling — done fully locally.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Taskdog?
&lt;/h2&gt;

&lt;p&gt;The name is arbitrary. I happened to see Datadog while using Taskwarrior, and went with "Task + dog = Taskdog." No deeper meaning.&lt;/p&gt;

&lt;p&gt;It's a task management system written in Python, with three interfaces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CLI&lt;/strong&gt; — quick command-line operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TUI&lt;/strong&gt; — full-screen terminal UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST API&lt;/strong&gt; — programmatic access&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Main Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Task Operations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add a task&lt;/span&gt;
taskdog add &lt;span class="s2"&gt;"READMEを書く"&lt;/span&gt; &lt;span class="nt"&gt;--priority&lt;/span&gt; 3 &lt;span class="nt"&gt;--tag&lt;/span&gt; docs

&lt;span class="c"&gt;# List tasks (table view)&lt;/span&gt;
taskdog table

&lt;span class="c"&gt;# Start / complete a task&lt;/span&gt;
taskdog start 1
taskdog &lt;span class="k"&gt;done &lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Schedule Optimization (The Core Feature)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Taskdog's core feature is auto-scheduling that never exceeds your daily work-hour limit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you add a 10-hour task with a deadline three days out, it automatically spreads the work across those three days. &lt;strong&gt;Weekends and holidays are skipped automatically&lt;/strong&gt;, so the schedule it produces is actually realistic.&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;# A 10-hour task with a 3-day deadline&lt;/span&gt;
taskdog add &lt;span class="s2"&gt;"レポート作成"&lt;/span&gt; &lt;span class="nt"&gt;--estimate&lt;/span&gt; 10h &lt;span class="nt"&gt;--deadline&lt;/span&gt; 2025-01-05

&lt;span class="c"&gt;# Run the optimizer&lt;/span&gt;
taskdog optimize
&lt;span class="c"&gt;# → Distributes across weekdays only, capped at 6 hours/day (default is configurable)&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%2F1cpaa34uk82vaecfk2a1.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%2F1cpaa34uk82vaecfk2a1.png" alt="Schedule optimization result" width="799" height="679"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It builds a schedule that respects priorities, deadlines, and dependencies — and stays within your work-hour cap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three practical algorithms:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskdog optimize                            &lt;span class="c"&gt;# greedy (default)&lt;/span&gt;
taskdog optimize &lt;span class="nt"&gt;--algorithm&lt;/span&gt; backward       &lt;span class="c"&gt;# deadline-driven&lt;/span&gt;
taskdog optimize &lt;span class="nt"&gt;--algorithm&lt;/span&gt; dependency_aware &lt;span class="c"&gt;# dependency-aware&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;greedy&lt;/td&gt;
&lt;td&gt;Schedule everything as early as possible&lt;/td&gt;
&lt;td&gt;When you want it done sooner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backward&lt;/td&gt;
&lt;td&gt;Work backward from deadlines (JIT)&lt;/td&gt;
&lt;td&gt;Deadline-driven work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dependency_aware&lt;/td&gt;
&lt;td&gt;Critical Path Method (CPM)&lt;/td&gt;
&lt;td&gt;When dependencies are heavy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are the three I actually use day to day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experimental algorithms for learning (six of them):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've also implemented &lt;code&gt;balanced&lt;/code&gt;, &lt;code&gt;priority_first&lt;/code&gt;, &lt;code&gt;earliest_deadline&lt;/code&gt;, &lt;code&gt;round_robin&lt;/code&gt;, &lt;code&gt;genetic&lt;/code&gt;, and &lt;code&gt;monte_carlo&lt;/code&gt;. These were built as experiments. See the repo for details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Difference from Motion/Reclaim:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motion/Reclaim: black-box AI (you don't know &lt;em&gt;why&lt;/em&gt; this schedule)&lt;/li&gt;
&lt;li&gt;Taskdog: transparent algorithms (source-readable, swappable)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gantt Chart View
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskdog gantt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get a Gantt chart right in the terminal. It also shows the daily load, so you can spot "this day is overpacked" at a glance.&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%2F4d76vwzctm61daxkiet8.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%2F4d76vwzctm61daxkiet8.png" alt="Gantt chart view" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  TUI (Full-Screen Mode)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;taskdog tui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The look and feel lean toward &lt;strong&gt;Vim/Neovim&lt;/strong&gt;.&lt;br&gt;
Real-time task search with &lt;code&gt;/&lt;/code&gt; is modeled after &lt;strong&gt;telescope.nvim&lt;/strong&gt;, so Neovim users should feel right at home.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Add task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Complete&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+P&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Command palette&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show help&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzie7metdapgh5w1croo3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzie7metdapgh5w1croo3.gif" alt="TUI demo" width="599" height="324"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Other Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task dependencies&lt;/strong&gt;: &lt;code&gt;taskdog add-dependency 2 1&lt;/code&gt; (task 2 starts after task 1 is done)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed tasks&lt;/strong&gt;: exclude meetings and other immovable events from optimization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip weekends/holidays&lt;/strong&gt;: only schedule on weekdays (supports Japanese public holidays)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markdown notes&lt;/strong&gt;: attach notes to any task&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag management&lt;/strong&gt;: categorize tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time tracking&lt;/strong&gt;: compare planned vs. actual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP support&lt;/strong&gt;: AI agents can manipulate tasks directly&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;Click + Rich&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TUI&lt;/td&gt;
&lt;td&gt;Textual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API&lt;/td&gt;
&lt;td&gt;FastAPI + Uvicorn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB&lt;/td&gt;
&lt;td&gt;SQLite + SQLAlchemy + Alembic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type checking&lt;/td&gt;
&lt;td&gt;mypy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linter&lt;/td&gt;
&lt;td&gt;Ruff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package manager&lt;/td&gt;
&lt;td&gt;uv&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Built with Clean Architecture, organized as a monorepo via uv workspaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/
├── taskdog-core/    # Business logic (no UI dependencies)
├── taskdog-client/  # HTTP API client
├── taskdog-server/  # FastAPI REST API
├── taskdog-ui/      # CLI/TUI
└── taskdog-mcp/     # Claude Desktop integration (MCP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The UI can be swapped without touching &lt;strong&gt;core&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;server&lt;/strong&gt; and &lt;strong&gt;ui&lt;/strong&gt; can be deployed independently&lt;/li&gt;
&lt;li&gt;Tests are easy to write&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Design Principles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Embrace That It's Personal
&lt;/h3&gt;

&lt;p&gt;Team features, cloud sync, collaboration — I cut all of it.&lt;/p&gt;

&lt;p&gt;Reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps things simple&lt;/li&gt;
&lt;li&gt;Protects privacy&lt;/li&gt;
&lt;li&gt;The peace of mind of being fully local&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Transparent Algorithms
&lt;/h3&gt;

&lt;p&gt;Instead of "the AI built your schedule," it should be possible to say "this algorithm produced this result."&lt;/p&gt;

&lt;p&gt;All three of the practical algorithms (greedy, backward, dependency_aware) are readable in source. If you don't agree with one, you can tweak it yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Following GTD Principles
&lt;/h3&gt;

&lt;p&gt;I borrowed ideas from David Allen's &lt;em&gt;Getting Things Done&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks should be concrete actions&lt;/li&gt;
&lt;li&gt;Dependencies should be explicit&lt;/li&gt;
&lt;li&gt;Regular review (&lt;code&gt;taskdog today&lt;/code&gt;, &lt;code&gt;taskdog gantt&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Was Hard, What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Parent-Child Task Feature That Didn't Work Out
&lt;/h3&gt;

&lt;p&gt;Early on I tried to implement parent/child tasks (subtasks).&lt;/p&gt;

&lt;p&gt;I figured "being able to decompose big tasks into smaller ones would be useful."&lt;/p&gt;

&lt;p&gt;But as I dug in, the problems piled up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should the parent task be scheduled? Just the children?&lt;/li&gt;
&lt;li&gt;Is the parent's estimate the sum of the children? Or independent?&lt;/li&gt;
&lt;li&gt;When all children are done, does the parent auto-complete?&lt;/li&gt;
&lt;li&gt;When you delete the parent, what happens to the children?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fit with the optimization algorithms was particularly awful. Every optimizer needed special-case logic for parent/child relationships, and the code kept growing more tangled.&lt;/p&gt;

&lt;p&gt;In the end I scrapped parent-child tasks and replaced them with &lt;strong&gt;dependencies + tags + notes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I realized I'm only juggling a handful of tasks at a time — there's no need to organize them in a tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating to Clean Architecture
&lt;/h3&gt;

&lt;p&gt;I started with a simple structure, but as features grew the code got messy. (At the very beginning it was literally just a pile of commands editing a JSON file.)&lt;/p&gt;

&lt;p&gt;Partway through I migrated to Clean Architecture. That was a lot of work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separating domain, application, and infrastructure layers&lt;/li&gt;
&lt;li&gt;Aligning the direction of dependencies&lt;/li&gt;
&lt;li&gt;Introducing the Use Case pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the payoff was worth it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All three interfaces — CLI, TUI, API — run on the same business logic&lt;/li&gt;
&lt;li&gt;Tests are easy to write&lt;/li&gt;
&lt;li&gt;Adding new features got much easier&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;24-hour task execution&lt;/li&gt;
&lt;li&gt;Recurring tasks&lt;/li&gt;
&lt;li&gt;Improving the scheduling algorithms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For details, see &lt;a href="https://github.com/Kohei-Wada/taskdog/blob/main/docs/DESIGN_PHILOSOPHY.md" rel="noopener noreferrer"&gt;DESIGN_PHILOSOPHY.md&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Building your own task manager for yourself might be one of the privileges of being a programmer.&lt;/p&gt;

&lt;p&gt;Taskdog is still under development and probably has bugs and rough edges. Even so, it fits my workflow perfectly.&lt;/p&gt;

&lt;p&gt;I think it's particularly suited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;People using Taskwarrior who wish it auto-generated schedules&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;People interested in Motion or Reclaim but unwilling to pay $20/month&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;People who want their task data to stay local&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;People who want a schedule built by transparent logic, not "because the AI said so"&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of that sounds like you, give it a try. Stars, issues, and PRs are all welcome.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/Kohei-Wada/taskdog" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was written with AI assistance and reviewed by the author.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cli</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Beyond AWK: Bringing Haskell into Unix Pipelines</title>
      <dc:creator>kohei_wada</dc:creator>
      <pubDate>Sun, 11 Oct 2026 15:38:48 +0000</pubDate>
      <link>https://dev.to/kohei_wada/beyond-awk-bringing-haskell-into-unix-pipelines-349m</link>
      <guid>https://dev.to/kohei_wada/beyond-awk-bringing-haskell-into-unix-pipelines-349m</guid>
      <description>&lt;h2&gt;
  
  
  1. A Problem Born from Daily Developer Life
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "I want to use Haskell more in real work."
&lt;/h3&gt;

&lt;p&gt;For any developer who has tasted the beauty of functional programming, this is a heartfelt wish. But the reality is that Haskell gets shunned as "impractical" or "too expensive to introduce," and there are almost no opportunities to use it at work.&lt;/p&gt;

&lt;p&gt;Couldn't we at least use Haskell for the small everyday tasks? When you stop and look, a shell pipeline really does resemble function composition.&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="nb"&gt;cat &lt;/span&gt;file | &lt;span class="nb"&gt;grep &lt;/span&gt;pattern | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pipeline = function composition. The more I sat with that intuition, the more convinced I became that Haskell ought to fit right in.&lt;/p&gt;

&lt;h3&gt;
  
  
  The AWK Wall
&lt;/h3&gt;

&lt;p&gt;When you want to do something a bit longer than a typical one-liner, AWK comes to mind. But...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"How do you write an array in AWK again?"&lt;/li&gt;
&lt;li&gt;"What's the syntax for a for loop...?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Haven't you ended up wasting time on Google, watching all the fun of shell trickery slip away?&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Moment of Inspiration: The Birth of phs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  My Three Big Problems
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;No chance to use Haskell at work&lt;/li&gt;
&lt;li&gt;Wanting more powerful processing inside shell pipelines&lt;/li&gt;
&lt;li&gt;Hating having to look up AWK syntax every time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I tried existing options like &lt;code&gt;stack script&lt;/code&gt; and &lt;code&gt;cabal script&lt;/code&gt;, but the first run is way too slow. Waiting several seconds for a trivial bit of processing just isn't practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Haskell ought to be more usable than this"
&lt;/h3&gt;

&lt;p&gt;Convinced of that, I figured &lt;strong&gt;fine, I'll just build it myself&lt;/strong&gt;. If we use &lt;code&gt;ghc -e&lt;/code&gt; for immediate execution, couldn't we drop Haskell directly into a pipeline?&lt;br&gt;
That is &lt;strong&gt;phs&lt;/strong&gt; (PipeLine Haskell Script).&lt;/p&gt;
&lt;h2&gt;
  
  
  3. phs in Everyday Work
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Example 0: stack script is too slow
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env stack&lt;/span&gt;
&lt;span class="nt"&gt;--&lt;/span&gt; stack script &lt;span class="nt"&gt;--resolver&lt;/span&gt; lts-22.33
main &lt;span class="o"&gt;=&lt;/span&gt; interact &lt;span class="o"&gt;(&lt;/span&gt;show &lt;span class="nb"&gt;.&lt;/span&gt; length &lt;span class="nb"&gt;.&lt;/span&gt; lines&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This code takes several seconds on its first run. So you end up reaching for &lt;code&gt;wc -l&lt;/code&gt; instead, and Haskell drifts further out of daily life.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With phs, it's instant:&lt;/strong&gt;&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="nb"&gt;cat &lt;/span&gt;file.txt | ./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'length'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 1: Character count per line
&lt;/h3&gt;

&lt;p&gt;In AWK:&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="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print length($0)}'&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But with phs, it's intuitive:&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="nb"&gt;cat &lt;/span&gt;files.txt | ./phs &lt;span class="s1"&gt;'length'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 2: Word count and character count
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print NF, length($0)}'&lt;/span&gt; file.txt

&lt;span class="c"&gt;# phs&lt;/span&gt;
./phs &lt;span class="s1"&gt;'\s -&amp;gt; (length (words s), length s)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 3: Sum of numbers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{sum=0; for(i=1;i&amp;lt;=NF;i++) sum+=$i; print sum}'&lt;/span&gt;

&lt;span class="c"&gt;# phs&lt;/span&gt;
./phs &lt;span class="s1"&gt;'sum . map read . words'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. A Thorough Comparison of AWK and Haskell (phs)
&lt;/h2&gt;

&lt;p&gt;The classic text-processing tool of UNIX culture is AWK. But phs covers what AWK is good at while pushing expressiveness even further.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;AWK&lt;/th&gt;
&lt;th&gt;phs (Haskell)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;First-run speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Instant (via &lt;code&gt;ghc -e&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Syntax&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom syntax (C-like)&lt;/td&gt;
&lt;td&gt;Standard Haskell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Functions / types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-ins are limited&lt;/td&gt;
&lt;td&gt;Haskell's standard library is available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Numeric processing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Floating point by default&lt;/td&gt;
&lt;td&gt;Precision managed via types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Relies on external commands&lt;/td&gt;
&lt;td&gt;Extensible by adding modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Must memorize a custom grammar&lt;/td&gt;
&lt;td&gt;Zero if you already know Haskell&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Comparison on basic text processing
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Count characters per line
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print length($0)}'&lt;/span&gt;

&lt;span class="c"&gt;# phs&lt;/span&gt;
./phs &lt;span class="s1"&gt;'length'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Take the first 10 characters of each line
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print substr($0, 1, 10)}'&lt;/span&gt;

&lt;span class="c"&gt;# phs&lt;/span&gt;
./phs &lt;span class="s1"&gt;'take 10'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Filter lines that are uppercase only
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (regex)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/^[A-Z]+$/'&lt;/span&gt;

&lt;span class="c"&gt;# phs (functional)&lt;/span&gt;
./phs &lt;span class="s1"&gt;'all isUpper'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comparison on numeric processing
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sum of numbers per line
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (imperative loop)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{sum=0; for(i=1;i&amp;lt;=NF;i++) sum+=$i; print sum}'&lt;/span&gt;

&lt;span class="c"&gt;# phs (function composition)&lt;/span&gt;
./phs &lt;span class="s1"&gt;'sum . map read . words'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sum of numbers across all lines
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (messy state handling)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{for(i=1;i&amp;lt;=NF;i++) total+=$i} END {print total}'&lt;/span&gt;

&lt;span class="c"&gt;# phs (simple function composition)&lt;/span&gt;
./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'sum . map read'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: word count per line
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AWK:&lt;/strong&gt;&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="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print NF}'&lt;/span&gt; file.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;phs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./phs &lt;span class="s1"&gt;'length . words'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Where the gap really shows: mathematical algorithms
&lt;/h3&gt;

&lt;h4&gt;
  
  
  First 10 terms of the Fibonacci sequence
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;AWK (a tangle of iteration):&lt;/strong&gt;&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="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN{a=1;b=1;for(i=1;i&amp;lt;=10;i++){print a;c=a+b;a=b;b=c}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;phs (an elegant recursive definition):&lt;/strong&gt;&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="nb"&gt;seq &lt;/span&gt;1 10 | ./phs &lt;span class="s1"&gt;'let fib n = if n &amp;lt;= 2 then 1 else fib (n-1) + fib (n-2) in fib . read'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Collatz conjecture
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;AWK (verbose imperative code):&lt;/strong&gt;&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="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{n=$1; while(n&amp;gt;1){if(n%2==0)n=n/2;else n=3*n+1; print n}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;phs (the formula expressed as-is):&lt;/strong&gt;&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="nb"&gt;seq &lt;/span&gt;10 | ./phs &lt;span class="s1"&gt;'let collatz n = if n == 1 then [1] else n : collatz (if even n then n `div` 2 else 3*n+1) in collatz . read'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Power set
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;AWK:&lt;/strong&gt; I don't want to (you'd need multi-dimensional arrays)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;phs:&lt;/strong&gt; You can write the mathematical definition verbatim&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"abc"&lt;/span&gt; | ./phs &lt;span class="s1"&gt;'let powerset [] = [[]]; powerset (x:xs) = powerset xs ++ map (x:) (powerset xs) in powerset'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced text processing
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Sorting lines
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (depends on an external command)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt;

&lt;span class="c"&gt;# phs (self-contained via built-in functions)&lt;/span&gt;
./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'sort'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Removing duplicate lines
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (needs external commands)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print}'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt;

&lt;span class="c"&gt;# phs (solved in one shot)&lt;/span&gt;
./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'nub'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reversing line order
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (requires a clunky implementation)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{a[NR]=$0} END {for(i=NR;i&amp;gt;0;i--) print a[i]}'&lt;/span&gt;

&lt;span class="c"&gt;# phs (intuitive)&lt;/span&gt;
./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'reverse'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Joining all lines into a single string
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# AWK (newline handling is a pain)&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{printf "%s%s", (NR&amp;gt;1?" ":""), $0} END {print ""}'&lt;/span&gt;

&lt;span class="c"&gt;# phs (natural)&lt;/span&gt;
./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'unwords'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWK is ideal for "simple row/column processing"&lt;/li&gt;
&lt;li&gt;phs shines at "mathematical or recursive processing," "type-safe aggregation," and "functional transformations," all writable as one-liners&lt;/li&gt;
&lt;li&gt;Especially for complex algorithms, AWK turns into verbose imperative code, while phs can express the mathematical definition directly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. The Edge in Mathematical Algorithms
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Collatz conjecture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AWK:&lt;/strong&gt; imperative and verbose&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="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{n=$1; while(n&amp;gt;1){if(n%2==0)n=n/2;else n=3*n+1; print n}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;phs:&lt;/strong&gt; the formula expressed directly&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="nb"&gt;seq &lt;/span&gt;10 | ./phs &lt;span class="s1"&gt;'let collatz n = if n == 1 then [1] else n : collatz (if even n then n `div` 2 else 3*n+1) in collatz . read'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Power set
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;AWK:&lt;/strong&gt; I don't want to&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;phs:&lt;/strong&gt; write the mathematical definition verbatim&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"abc"&lt;/span&gt; | ./phs &lt;span class="s1"&gt;'let powerset [] = [[]]; powerset (x:xs) = powerset xs ++ map (x:) (powerset xs) in powerset'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. The Simplicity of phs
&lt;/h2&gt;

&lt;p&gt;The implementation of phs is shockingly simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Command-line parsing&lt;/li&gt;
&lt;li&gt;Immediate evaluation via &lt;code&gt;ghc -e&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Config file loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's all you need for a lightweight implementation that works. The secret to its speed is &lt;code&gt;ghc -e&lt;/code&gt;'s &lt;strong&gt;immediate execution with no precompilation required&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Current limitations and future improvements
&lt;/h3&gt;

&lt;p&gt;Because phs is a lightweight implementation, it has a few constraints:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;String display issue:&lt;/strong&gt;&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt; | ./phs &lt;span class="s1"&gt;'id'&lt;/span&gt;
&lt;span class="c"&gt;# Output: "hello"  (double quotes are included)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because results are displayed using the &lt;code&gt;Show&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;But anyone who regularly uses the shell can just do:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt; | ./phs &lt;span class="s1"&gt;'id'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;
&lt;span class="c"&gt;# Output: hello  (double quotes removed)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem solved (lol).&lt;/p&gt;

&lt;p&gt;The current simple implementation stays lightweight by running every result through &lt;code&gt;show&lt;/code&gt; uniformly. It's a design that follows the Unix philosophy of "rather than chasing perfection, get something working first." Any fine-grained tweaking is best handled by combining it with other shell tools — that's the Unix way!&lt;/p&gt;

&lt;h2&gt;
  
  
  7. How phs Sets Itself Apart from Existing Tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;First run&lt;/th&gt;
&lt;th&gt;Subsequent runs&lt;/th&gt;
&lt;th&gt;Learning cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;stack script&lt;/td&gt;
&lt;td&gt;3-5 sec&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cabal script&lt;/td&gt;
&lt;td&gt;2-4 sec&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWK&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;High (you forget)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;phs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Instant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Instant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Low&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Learning and research
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Algorithm exploration&lt;/li&gt;
&lt;li&gt;Generating and analyzing number sequences
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Sum of squares&lt;/span&gt;
&lt;span class="nb"&gt;seq &lt;/span&gt;1 100 | ./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'sum . map (\x -&amp;gt; let t = read x in t * t)'&lt;/span&gt;

&lt;span class="c"&gt;# Searching for perfect numbers&lt;/span&gt;
&lt;span class="nb"&gt;seq &lt;/span&gt;1 1000 | ./phs &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="s1"&gt;'let isPerfect n = sum [i | i &amp;lt;- [1..n-1], n `mod` i == 0] == n in \xs -&amp;gt; filter isPerfect $ map read xs'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Looking Ahead
&lt;/h2&gt;

&lt;p&gt;phs has made "everyday Haskell" a reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No need to recall AWK syntax&lt;/li&gt;
&lt;li&gt;The beauty of functional programming, every day&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Getting Started with phs Today
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Kohei-Wada/phs.git
&lt;span class="nb"&gt;cd &lt;/span&gt;phs
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x phs

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt; | ./phs &lt;span class="s1"&gt;'reverse'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you'll notice: "oh, this is actually handy." (lol)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt; &lt;a href="https://github.com/Kohei-Wada/phs" rel="noopener noreferrer"&gt;https://github.com/Kohei-Wada/phs&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Let's bring Haskell more into daily life!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;phs is more than just a tool. It's a first step toward folding Haskell into everyday work. Why not join me in bringing the beauty of functional programming into your daily tasks?&lt;/p&gt;

&lt;p&gt;I'm pretty sure it'll make writing code a lot more fun.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was written with AI assistance and reviewed by the author.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>cli</category>
      <category>haskell</category>
      <category>programming</category>
    </item>
    <item>
      <title>I built supernemawashi — a Claude Code plugin that manages psychological profiles for talking to colleagues</title>
      <dc:creator>kohei_wada</dc:creator>
      <pubDate>Sun, 11 Oct 2026 08:29:39 +0000</pubDate>
      <link>https://dev.to/kohei_wada/i-built-supernemawashi-a-claude-code-plugin-that-manages-psychological-profiles-for-talking-to-37m2</link>
      <guid>https://dev.to/kohei_wada/i-built-supernemawashi-a-claude-code-plugin-that-manages-psychological-profiles-for-talking-to-37m2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In conversations with colleagues and stakeholders, working out "will this phrasing land with this person, or step on a landmine?" from scratch every time is quietly exhausting. There's a limit to how many people I can keep in my head, and I forget anyway.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/Kohei-Wada/supernemawashi" rel="noopener noreferrer"&gt;supernemawashi&lt;/a&gt;, a Claude Code plugin that solves this by &lt;strong&gt;managing profiles as data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The workflow: collect facts from Slack / Gmail / Calendar / GitHub, classify them with psychology frameworks, generate situation-specific DO / DON'T rules, and call them up when I'm writing a reply. Everything runs locally — nothing is sent anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Saying "most of an engineer's job is talking to people" is blunt, but it's true. I spend more time asking, reporting, arguing, and persuading than I do writing code. And for all of it, I'm working out the optimal phrasing for each person's type, every single time. That wears you down.&lt;/p&gt;

&lt;p&gt;Concretely, situations like these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I phrased something "too bluntly" for someone and stepped on a landmine. I tell myself I'll be careful next time, then forget.&lt;/li&gt;
&lt;li&gt;One person is convinced by numbers; another responds better to a story. Do it backwards and you get ignored.&lt;/li&gt;
&lt;li&gt;One person acts when you push in a meeting; another shuts down when you push in a meeting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Remembering it from experience" breaks down as the number of people grows. With someone I don't have committed to memory, I start from zero every time — and even with people I think I remember, I forget things.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it solves the problem
&lt;/h2&gt;

&lt;p&gt;The idea itself is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Record &lt;strong&gt;facts&lt;/strong&gt; about the person (who said what, when) as data&lt;/li&gt;
&lt;li&gt;Classify the facts with &lt;strong&gt;psychology frameworks&lt;/strong&gt; (defense mechanisms / conflict modes / ego states / motivators / biases / attachment style)&lt;/li&gt;
&lt;li&gt;From the classification, generate &lt;strong&gt;situation-specific DO / DON'T rules&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;When writing a reply, pull up that person's profile plus the rules for the relevant situation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words, &lt;strong&gt;pre-compute "how do I talk to this person" and keep it in a file&lt;/strong&gt; — so I don't re-derive it on every reply.&lt;/p&gt;

&lt;p&gt;Profiles live in &lt;code&gt;~/.local/share/supernemawashi/profiles/&amp;lt;person-name&amp;gt;/&lt;/code&gt;, entirely local. Even when it reads Slack / Gmail over MCP, the collected data never leaves the machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills
&lt;/h2&gt;

&lt;p&gt;The operational skills are all verb-first under a &lt;code&gt;nemawashi-&lt;/code&gt; prefix:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Skill&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-collect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Collect facts from MCP sources (Slack / Gmail / Calendar / GitHub) into a profile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-analyze&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classify the gathered facts with psychology frameworks, generate situation DO / DON'T rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-show&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;View profiles (list / drill into one / aggregated situation rules)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-discover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Find people you talk to but haven't profiled yet, from MCP sources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dashboard of stale profiles (analyses gone old)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-note&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manually add a one-line fact MCP can't see (1on1, phone, hallway chat)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-reply&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Load only the frameworks relevant to the situation, generate 2–3 reply drafts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-migrate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Convert old-format profiles to the new format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nemawashi-issue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shape an improvement idea into the house style and file it as a GitHub issue&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A basic workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1] /nemawashi-collect "John"
        ↓ collect facts from MCP sources
[2] /nemawashi-analyze "John"
        ↓ classify per framework, generate DO/DON'T
[3] /nemawashi-reply "How should I reply to John about the deadline?"
        ↓ load John's profile + only the relevant frameworks
[4] 2–3 drafts come back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install is via the marketplace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add Kohei-Wada/supernemawashi
/plugin install supernemawashi@supernemawashi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the Claude Code session and the &lt;code&gt;using-supernemawashi&lt;/code&gt; entry-point skill is injected via a SessionStart hook — from there it runs in natural language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The discomfort of "turning people into data"&lt;/strong&gt;: profiles are for &lt;em&gt;people you talk to&lt;/em&gt;, not surveillance targets. This isn't built for profiling random coworkers behind their backs (and the MCP sources only run through your own account).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP rate limits&lt;/strong&gt;: hammering Slack or Gmail hits limits. The &lt;code&gt;--all&lt;/code&gt; bulk operations are throttled to batches of 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale profiles&lt;/strong&gt;: a profile not analyzed for a month is less trustworthy. &lt;code&gt;nemawashi-check&lt;/code&gt; surfaces staleness, and &lt;code&gt;nemawashi-update --all&lt;/code&gt; re-analyzes everything at once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Collect everyone" is heavy&lt;/strong&gt;: collect is MCP-bound and slow, while analyze is local-file-only and fast — so the two are split into separate skills, letting you re-run just the analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For someone I have a profile on, the time spent figuring out "how do I phrase this" dropped from ~5 minutes to ~30 seconds.&lt;/li&gt;
&lt;li&gt;For "someone I haven't talked to in a while" or "someone I rarely talk to," facts auto-collect from past Slack / Gmail, so the first-contact cost went down.&lt;/li&gt;
&lt;li&gt;I built a profile of myself and ran analyze on it — my own coping patterns became visible, which turned out to be a bit therapeutic (an unexpected side effect).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The cost of figuring out "how to talk to this person" from scratch every time can be cut down by turning it into data&lt;/li&gt;
&lt;li&gt;supernemawashi wires fact collection / psychological analysis / situation-rule generation / reply drafting into a single plugin&lt;/li&gt;
&lt;li&gt;Profile data never leaves your machine; MCP sources are read only through your own account&lt;/li&gt;
&lt;li&gt;It installs as a Claude Code plugin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repo is here: &lt;a href="https://github.com/Kohei-Wada/supernemawashi" rel="noopener noreferrer"&gt;supernemawashi (GitHub)&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post was written with AI assistance and reviewed by the author.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>I made a terminal task manager, got featured by the creator of Textual, and Reddit banned me 🤣</title>
      <dc:creator>kohei_wada</dc:creator>
      <pubDate>Wed, 25 Mar 2026 04:54:23 +0000</pubDate>
      <link>https://dev.to/kohei_wada/i-made-a-terminal-task-manager-got-featured-by-the-creator-of-textual-and-reddit-banned-me-cca</link>
      <guid>https://dev.to/kohei_wada/i-made-a-terminal-task-manager-got-featured-by-the-creator-of-textual-and-reddit-banned-me-cca</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.amazonaws.com%2Fuploads%2Farticles%2Fpg3hkjmy0hxhwrl38vv9.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.amazonaws.com%2Fuploads%2Farticles%2Fpg3hkjmy0hxhwrl38vv9.png" alt="TUI" width="799" height="395"&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.amazonaws.com%2Fuploads%2Farticles%2Fqo6ym8d550pw6d01ju52.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.amazonaws.com%2Fuploads%2Farticles%2Fqo6ym8d550pw6d01ju52.png" alt="cli gantt" width="799" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever spent weeks building an open-source project, finally launched it, and then had Reddit's spam filter silently delete your post because your account was too new?&lt;/p&gt;

&lt;p&gt;That was my experience launching &lt;strong&gt;taskdog&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But the Reddit drama isn't the point. The real story is why I built a terminal task manager from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: No task manager fit my workflow
&lt;/h2&gt;

&lt;p&gt;I was inspired by &lt;a href="https://taskwarrior.org/" rel="noopener noreferrer"&gt;Taskwarrior&lt;/a&gt; — powerful, keyboard-driven, terminal-native. But I wanted a proper TUI and a local API I could build on top of. Nothing out there quite fit, so I built my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Design Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why no subtasks?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most task managers let you nest tasks infinitely. I removed subtasks entirely. Dependencies + tags cover 99% of personal task organization, and keeping the structure flat makes the schedule optimizer dramatically simpler. I documented the full reasoning in &lt;a href="https://github.com/Kohei-Wada/taskdog/blob/main/docs/DESIGN_PHILOSOPHY.md" rel="noopener noreferrer"&gt;&lt;code&gt;DESIGN_PHILOSOPHY.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Clean Architecture for a personal tool?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The codebase is split into three packages: &lt;code&gt;taskdog-core&lt;/code&gt; (business logic), &lt;code&gt;taskdog-server&lt;/code&gt; (FastAPI REST API), &lt;code&gt;taskdog-ui&lt;/code&gt; (CLI/TUI). Overkill for a personal project? Maybe. But it forced me to keep business logic completely independent of the UI and transport layer — and it paid off when I added the API server without touching the core.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Full-screen TUI powered by &lt;a href="https://github.com/Textualize/textual" rel="noopener noreferrer"&gt;Textual&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;FastAPI + SQLite backend running locally&lt;/li&gt;
&lt;li&gt;9 scheduling optimization algorithms&lt;/li&gt;
&lt;li&gt;Time tracking with planned vs actual comparison&lt;/li&gt;
&lt;li&gt;Gantt chart view&lt;/li&gt;
&lt;li&gt;Task dependencies with circular detection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it instantly (no install needed)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; ghcr.io/kohei-wada/taskdog:demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spins up the server and launches the TUI in one shot, with demo data preloaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reception
&lt;/h2&gt;

&lt;p&gt;After shipping it, some nice things happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Featured on &lt;a href="https://terminaltrove.com/taskdog/" rel="noopener noreferrer"&gt;Terminal Trove&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Featured on &lt;a href="https://www.linuxlinks.com/taskdog-task-management-system/" rel="noopener noreferrer"&gt;LinuxLinks&lt;/a&gt; in the CLI/TUI/Productivity category&lt;/li&gt;
&lt;li&gt;Will McGugan — creator of Textual, the library powering the TUI — &lt;a href="https://x.com/willmcgugan/status/2027377375156080742?s=20" rel="noopener noreferrer"&gt;said&lt;/a&gt;: &lt;em&gt;"The author of this project has clearly got a good eye for design in the terminal"&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Built with the help of Claude Code (credited as contributor in the repo). Architecture, algorithms, and all design decisions are my own.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/Kohei-Wada/taskdog" rel="noopener noreferrer"&gt;https://github.com/Kohei-Wada/taskdog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>tui</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
