Today I Learned

Bite-sized things I pick up day to day โ€” tools, tricks, and tidbits worth remembering.

Expand-Contract Pattern

Apr 7, 2026

pattern
In software we often need to make changes. When those changes are non-destructive, such as adding fields to an entity, then we just do it and we're done. But when the changes are destrucvie, such as changing existing fields or deleting some, then we have a problem.
If everything is internal stuff, meaning the interface surface does not change, we can still just make changes and be done with it. But if we cross interface surfaces of interfaces between teams, or between deployable units, then we cannot just get it done in one go. In this case, we can halt everything and make the changes, but that is most of the times no option.
This then means we have to make the changes and migrate while keeping everything operational. A pattern to achieve this is as following
  1. Add the changes in a non-destructive way, such that we provide both the old and the new at the same time
  2. Migrate the consumers from the old to the new
  3. Delete the old stuff
I have used this pattern multiple times, but just recently did I learn that it has a name. It seems to be called "Expand and Contract" or "Parallel Change". The steps can be generalized as
  1. expand
  2. migrate
  3. contract
I didn't have a name for it, and now I have, making it easier to communiciate this with peers. Great!

Built a custom todo manager

Apr 6, 2026

ai
tooling
I have managed my todos in a single todo file up to now. With todos here, I do no mean daily tasks like do this work task etc. but rather an ad hoc improvement to my coding setup / a new tool I want to try out / a new workflow I want to set up etc. It has worked well so far. Initially it was just a list, then it grew so I needed to add priority info so I could decide on first glance where to chip off of every morning. I added 3 tier emojis to indiciate low, medium and high priority. Then it grew more and I decided to create sections per category like nvim, terminal, AI etc. This then worked for months more or less.
But now there's just so many tasks every day that are newly added that I really need a better system to classify and manage all the tasks. I tried multiple existing applications but none of them quite worked for me. The application had to be a terminal-based application for me to work. That's is most important requirement. And it turns out there aren't too many to-do or task management applications that fulfill this. The most predominant one seems to be taskwarrior. I tried it out, but it just didn't fit my workflow. So the natural conclusion in this day and age of vibe coding that allows for almost zero cost custom tooling is to create my own.
The tool
I used golang together with lipgloss and bubbletea For the terminal UI. Each task has a priority, a category, a status of active and done, a title, and a body. You can have the interactive funnel UI, but you can also edit and delete stuff from the CLI. The CLI functionality basically allows for bulk updates and deletes through AI agents. State is persisted in a single JSON file. This JSON file is checked into one of my Git repositories, so everything's safe. I can filter by priority. I can change the view to show everything clustered by priority or clustered by category. Adding a functionality just takes me a minute or two, so going forward I'll keep customizing and personalizing this.
My recent conclusion really has been, if you have a common general task, look for general tools and use one that seems good to you. But if you can't find anything, just make your own. These tools are really just for personal use, as well as there is no real risk if they stop working or become hard to maintain. And so this is where AI vibe coding really shines.

Creating custom raycast extensions

Apr 4, 2026

raycast
productivity
At my company, we use notion extensively. I often found myself clicking through things to open notion pages. Or, I was looking at my bloated up favorites list to find the link.
I wondered if there is no better way to do this that is quicker and easier. I looked into the main notion extension, but that did not work for me. The page search was just too broad, and filter's could not be preset. 90% of the time I look at the same 10 pages. Given this fact I just wanted those to be listed. Plain and simple.
Making a raycast extension is actually really easy, especially if you only intend to use it yourself locally. It took me about 10min to create and iterate on with Claude Code, to get something personalized for myself.
Basically, the essence of my extension is just the below tsx. I have a fixed list of pages, with custom aliases to show, and i can fuzzy search them and open them easily.
I registered this, and then assigned the cmd+shift+N hotkey to it. Now I can open my most used pages in about 2s consistenly.
import { Action, ActionPanel, closeMainWindow, List, popToRoot } from "@raycast/api";

interface Page {
  alias: string;
  name: string;
  icon: string;
  url: string;
}

// Pages you always want quick access to
const pinned: Page[] = [
  {
    alias: "1on1",
    name: "1on1 for Lukas",
    icon: "๐Ÿช™",
    url: "https://www.notion.so/<organization-name>/<page-id>",
  },

  ...
];

// Temporary pages for current work โ€” rotate as needed
const transient: Page[] = [
  {
    alias: "hardlimit",
    name: "Project Hardlimits",
    icon: "๐Ÿ“„",
    url: "https://www.notion.so/<organization-name/<page-id>",
  },
];

function PageItem({ page }: { page: Page }) {
  return (
    <List.Item
      icon={page.icon}
      title={page.alias}
      subtitle={page.name}
      actions={
        <ActionPanel>
          <Action.OpenInBrowser
            url={page.url}
            onOpen={() => {
              popToRoot({ clearSearchBar: true });
              closeMainWindow();
            }}
          />
        </ActionPanel>
      }
    />
  );
}

export default function Command() {
  return (
    <List searchBarPlaceholder="Filter pages...">
      {transient.length > 0 && (
        <List.Section title="Transient">
          {transient.map((page) => (
            <PageItem key={page.url} page={page} />
          ))}
        </List.Section>
      )}
      <List.Section title="Pinned">
        {pinned.map((page) => (
          <PageItem key={page.url} page={page} />
        ))}
      </List.Section>
    </List>
  );
}
You use the Raycast provided components like List and List.Section, which results in visually and functionally seamless extensions.

ๅทฅๆ•ฐ่ฆ‹็ฉ

Apr 3, 2026

software development
ๅทฅๆ•ฐ่ฆ‹็ฉใ‚’ใ™ใ‚‹ใจใใซใ€ไปฅไธ‹ใฎ๏ผ’ใคใŒใƒˆใƒฌใƒผใƒ‰ใ‚ชใƒ•็Šถๆ…‹ใซใ‚ใ‚‹ใ€‚
  • ใฉใ“ใพใงๆญฃ็ขบใซ่ฆ‹็ฉใ‚‚ใ‚Šใ‹
  • ใฉใ‚Œใปใฉ่ฆ‹็ฉใ‚‚ใ‚Šใซๆ™‚้–“ใ‚’ใ‹ใ‘ใ‚‹ใ‹
ๆญฃ็ขบใซ่ฆ‹็ฉใ‚‚ใ‚ใ†ใจๆ€ใˆใฐๆ€ใ†ใปใฉ่ฉณใ—ใ่ชฟในใชใ„ใจใ„ใ‘ใชใใฆใ€ใใฎ็ตๆžœๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใ€‚ ๆ„Ÿ่ฆš็š„ใซใฏๆŒ‡ๆ•ฐ้–ขๆ•ฐ็š„ใชๆฏ”ไพ‹ใซ่ฟ‘ใ„ใ‹ใ‚‚ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ ใ–ใฃใจๆ•ฐๅ€คใ‚’ๅ‡บใ™ใฎใชใ‚‰ใฐ๏ผ‘๏ผ็ง’ใงใ‚‚ใงใใ‚‹ใŒใ€ใใ“ใ‹ใ‚‰ใ€่ฉณ็ดฐใซ่ฆ‹ใฆใ„ใใจๆ€ฅใซๆ™‚้–“ใฏๅข—ๅคงใ—ใฆใ„ใฃใฆใ€ๆœ€็ต‚็š„ใซใฏใ™ในใฆใฎๅฎŸ่ฃ…็ฎ‡ๆ‰€ใจใใฎๅ…ทไฝ“็š„ใชๅฎŸ่ฃ…ๆ–นๅผใพใงๆ˜Žใ‚‰ใ‹ใซใ™ใ‚‹ใ“ใจใซใชใ‚‹ใ€‚ ใ“ใ“ใพใงใใ‚‹ใจใ€ๅฎŸ้š›ใซๅฎŸ่ฃ…ใ™ใ‚‹ใฎใจๅทฎใŒใชใ„ๆ™‚้–“ใŒใ‹ใ‹ใ‚‹ใ“ใจใซใชใ‚‹ใ€‚ ๅฎŸ่ณชๅฎŸ่ฃ…ใ—ใฆใ„ใ‚‹ใฎใจใ‹ใ‚ใ‚‰ใชใ„ใ€‚ ใ€Œใฉใ‚Œใปใฉๅทฅๆ•ฐใ‹ใ‹ใ‚Šใใ†๏ผŸใ€ใจใ„ใ†่ปฝใ„่ณชๅ•ใซๅฏพใ—ใฆใ€ๅ•ใ„ใ‚’ไพ้ ผใจๅ‹˜้•ใ„ใ—ใฆๅฎŸ่ฃ…ใ—ใฆใ„ใ‚‹ใ‚ˆใ†ใช็Šถๆ…‹ใซใ‚ใŸใ‚‹ใจใ‚‚ใ„ใˆใใ†ใ€‚ ใ“ใ‚Œใฏใพใ‚ใ‚ˆใใชใ„ใ‚ˆใชใ€‚
ใ‚ขใ‚ธใƒฃใ‚คใƒซใฟใŸใ„ใช็’ฐๅขƒใ ใจๅทฅๆ•ฐ่ฆ‹็ฉใฏๅˆคๆ–ญๆๆ–™ใจใ—ใฆไฝฟใ‚ใ‚Œใ‚‹ใ€‚ๅˆคๆ–ญใฏใ€ŒไปŠๅ›žใฎใ‚นใ‚ณใƒผใƒ—ใซๅซใ‚ใ‚‹ใ‹ๅฆใ‹ใ€ใฎ๏ผ’ๆŠžใงใ‚ใ‚‹ใ“ใจใ‚‚ๅคšใ„ใ€‚ ใ“ใฎ๏ผ’ๆŠžใฎๅˆคๆ–ญใ‚’ใ™ใ‚‹ใŸใ‚ใฎๆๆ–™ใ‚’ๆไพ›ใ™ใ‚‹ใ“ใจใซใชใ‚‹ใ€‚ ่ฆ‹็ฉใ‚‚ใ‚ŠใŒใƒฉใƒ•ใ™ใŽใฆ๏ผ‘้€ฑ้–“ใ ใจๆ€ใฃใŸใ‚‚ใฎใŒ่“‹ใ‚’้–‹ใ‘ใŸใ‚‰4ใ‹ๆœˆใ‚‚ใ‹ใ‹ใฃใŸใจใชใ‚‹ใ“ใจใ‚‚ใ‚ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ ใŸใ ใ—ใ€ๅคšใใฎๅ ดๅˆใฏใใ†ใ„ใ†่‡ชไฝ“ใ‚‚่ตทใ“ใ‚Šใฅใ‚‰ใ„ใ€‚ ๏ผ‘้€ฑ้–“ใ ใจไผใˆใฆใ€ใ˜ใ‚ƒใ‚ใ‚„ใ‚ใ†ใจใชใ‚‹ใ€‚ๅฎŸ้š›ใซใ‚„ใ‚‹ใจใใซใ‚‚ใฃใจ่ฉณ็ดฐใซ่ชฟในใ‚‹ใจใ€Œใ‚ใƒผใ€ใ“ใ‚Œใฏๆ€ใฃใŸใ‚ˆใ‚Šๆ™‚้–“ใ‹ใ‹ใ‚‹ใชใ€ใจ้…ใใจใ‚‚ใใฎๆ™‚็‚นใง็™บ่ฆšใ—ใ€ใใฎๆ™‚็‚นใงๅ†ๅบฆๅˆคๆ–ญใƒป่ชฟๆ•ดใ‚’ใ™ใ‚‹ใ“ใจใซใชใ‚‹ใฎใงใ€‚ ใฎใงใ€ใใ“ใพใง๏ผ‘ใคใฎ่ฆ‹็ฉใ‚‚ใ‚Šใซๆ™‚้–“ใ‚’ๆŽ›ใ‘ใฆใ‚‚่ฟ”ใฃใฆใ€ๆ™‚้–“ๅŠน็އใŒไฝŽไธ‹ใ™ใ‚‹ใ“ใจใซใชใ‚‹ใฎใงใ€ใƒฉใƒ•ใช่ฆ‹็ฉใ‚‚ใ‚Šใจ้€Ÿใ„ๆ„ๆ€ๆฑบๅฎšใ‚’็›ฎๆŒ‡ใ™ใ€‚ ใ‚‚ใกใ‚ใ‚“ใ€ไธๅฏ้€†ใงใ‚ใฃใŸใ‚Šใงใ‚‚ใฃใจๆ…Ž้‡ใซใชใ‚‹ในใไบ‹ๆ…‹ใ‚‚ใ‚ใ‚‹ใฎใงใ€ใใ“ใฏใ‚‚ใฃใจใ˜ใฃใใ‚Šๆคœ่จŽใ™ใ‚Œใฐใ„ใ„ใ€‚
็Ÿฅ่ฆ‹ใจใ—ใฆใฏ
  • ๅทฅๆ•ฐ่ฆ‹็ฉใ‚‚ใ‚Šใฏใ‚ใใพใง่ฆ‹็ฉใ‚‚ใ‚Šใ€‚ๅคšใใฎๅ ดๅˆใฏๅˆคๆ–ญๆๆ–™ใ€‚ไธ€ๅฎšใฎ่ชคๅทฎใฏ่จฑๅฎนใ•ใ‚Œใ‚‹ใ‚‚ใฎใ€‚
  • ๆญฃ็ขบใซใ—ใ‚ˆใ†ใจๆ€ใ†ใปใฉใ€่ฆ‹็ฉใ‚‚ใ‚Š่‡ชไฝ“ใฎๅทฅๆ•ฐใŒ่†จใ‚‰ใฟใ€ๆœ€็ต‚็š„ใซใฏๅฎŸ่ฃ…ใ™ใ‚‹ใฎใจๅทฎ็•ฐใŒใชใ„้ ˜ๅŸŸใซใพใง่ฟ‘ใฅใ
  • ใƒฉใƒ•ใช่ฆ‹็ฉใ‚‚ใ‚ŠใŒๅคงๅน…ใซใฏใšใ‚Œใฆใ‚‚ใ€ๅฎŸ่ฃ…ใŒ่ฟ‘ใฅใ„ใŸใ‚‰ใ‚ˆใ‚Š่งฃๅƒๅบฆ้ซ˜ใ็™บ่ฆšใ—ใ€ใใฎๆ™‚็‚นใงใ‚‚ใพใŸ่ชฟๆ•ดใ™ใ‚Œใฐใ„ใ„
  • ๆ„ๆ€ๆฑบๅฎšใŒๅคšใ„ใฎใงใ€๏ผ‘ใค๏ผ‘ใคใซๅคšๅคงใชๆ™‚้–“ใ‚’ใ‹ใ‘ใšใ€ไธ€ๅฎšใฎ็ฒพๅบฆใงใƒ‘ใƒณใƒ‘ใƒณ้€ฒใ‚ใ‚‹ๆ–นใŒ้‡่ฆใชๅ ด้ขใ‚‚ๅคšใ„
ใจใ„ใ†ใจใ“ใ‚ใงใ—ใ‚‡ใ†ใ‹ใ€‚ ่‡ชๅˆ†ใฏใ‹ใชใ‚Šๆ…Ž้‡ๆดพใชใฎใงใ€ๆ€งๆ ผ็š„ใซใฏใ€Œๆ™‚้–“ๅŠน็އใ€ใจใ€Œ้€Ÿใ„ๆ„ๆ€ๆฑบๅฎšใ€ใ‚’ๆ„่ญ˜ใ™ใ‚‹ๆ–นๅ‘ใธ่‡ชๅˆ†ใ‚’ๅ‘ใ‹ใ‚ใ›ใ‚‹ใ“ใจใŒ้‡่ฆใ ใจๆ„Ÿใ˜ใฆใ„ใ‚‹ใ€‚ ้€†ใฎๆ€งๆ ผใฎๆ–นใชใ‚‰ใฐใ€Œใ‚ˆใ‚Šใกใ‚ƒใ‚“ใจใ™ใ‚‹ใ€ๆ–นใธๆ„่ญ˜ใ™ใ‚‹ใ“ใจใซใชใ‚‹ใฎใ‹ใ‚‚ใ—ใ‚Œใชใ„ใ€‚ ไฝ•ไบ‹ใ‚‚็พๅœจๅœฐใจ็†ๆƒณใ‚’ๆŠŠๆกใ—ใ€ใใฎๅทฎๅˆ†ใ‚’ๅŸ‹ใ‚ใ‚‹ใƒ™ใ‚ฏใƒˆใƒซใซๅพ“ใฃใฆ้€ฒใ‚€ใ“ใจใซใชใ‚‹ใฎใงๆฑŽ็”จ็š„ใช็ญ”ใˆใฏใชใ„ใ€‚
ๆœ€ๅพŒใซใ€AI ใ‚’้ง†ไฝฟใ™ใ‚Œใฐใ€ใ‹ใชใ‚Š็ฒพๅบฆใฎ้ซ˜ใ„่ฆ‹็ฉใ‚‚ใ‚Šใ‚’็Ÿญๆ™‚้–“ใงๅ‡บใ›ใ‚‹ใ‹ใ‚‚ใ—ใ‚Œใชใ„ใฎใงใ€ใใ“ใ‚‚่ฉฆใ—ใฆใ„ใใŸใ„ใ€‚ ๅฐ‘ใชใใจใ‚‚ใ€ๅฟ…่ฆใซใชใ‚Šใใ†ใชไฝœๆฅญใƒปๆ‰‹้ †ใฎๅˆ—ๆŒ™ใ ใ‘ใงใ‚‚ๅ‡บใ—ใฆใ‚‚ใ‚‰ใฃใฆใ€ใใ‚Œใ‚’ใจใ‚‚ใซ่ฆ‹็ฉใ‚‚ใ‚Šใ™ใ‚Œใฐใ€ใใ‚Œใ ใ‘ใงใ‚‚ๆ™‚้–“ใ‚’ใ‹ใ‘ใšใซ็ฒพๅบฆใŒไธŠใŒใ‚Šใใ†ใ€‚
่ฆ‹็ฉใ‚‚ใ‚Šใฏ้›ฃใ—ใ„ๅ•้กŒใ€‚ใ‚„ใฃใฆใ„ใไธŠใง็ตŒ้จ“ๅ€คใ‚’่“„ใˆใฆใ„ใฃใฆใ€่ƒฝๅŠ›ใ‚’็ ”ใŽๆพ„ใพใ—ใฆใ„ใใŸใ„ใ€‚

External & Internal Quality of Software

Apr 2, 2026

software-development
Let's think about what external & internal quality actually mean and what their relationship is.
External quality is the externally observable quality of software. Does you software look good? Is it easy to use? Does it run fast? Is the security rigid? Those kinds of things.
Internal quality is the internally observable quality of you software... what does that mean? This is way more vague than the external one. There is no checklist we have all agreed on as to what internal quality means. It requires deep understanding of the product, of the software, of the vision ahead to interpret whether our current situtation is high quality or not.
Is it easy to extend and add new features to? Well that depends on which part we are talking about. Some are some not. Well, we really care about the parts that we actually intend or are highly likely to extend, but that is only known to a person with a deep understanding of the product vision.
Is it easy to undertstand? (which also partially feeds into easy to extend) Well, who is the audience? How experienced are they? Are the domain concepts quite common sense things, or are they really domain-specific and need a detailed explanation?
So I think internal quality is quite hard to grasp. You could just say have tests, write loosely coupled code, have a unified and good way to handle errors etc. These are true and important. But, internal quality is not of value by itself. It is only valuable insofar it enables us to uphold and improve the external quality. (which is where the true raison d'etre of our software lies) Internal quality tends to become a checklist of things that are way too generalized, and way too simplified. The amount and type of "internal quality" required is very differnt per software product.
To say "internal quality" makes it seem that we have high quality and low quality. And then we say that automated tests improve internal quality. Well that means to have "high quality" we must have automated tests. Well, some products probably won't need too many automated test. Especially when we have other means to test external quality & the product features are frozen. What "internal quality" means differs from product to product because their goals and situation differs. So the answer is, we can lay out high-level guiding principles & axis alongst which we should inspect our software to make "high internal quality", but there is no simple checklist with things like many autmoated tests are required for high quality.

So
  • External quality โ†’ the end
  • Internal quality โ†’ the means to sustain the end
And they can each be further split into (but no limiting to)
  • External quality โ€” does what it should
    • Correct
      • Does the right thing
    • Usable
      • People can actually use it
    • Performant / Reliable
      • Does it consistently and well
  • Internal quality โ€” easy and safe to change
    • Easy to understand
      • Clear naming and structure
      • Well defined boundaries / separation of concerns
    • Easy to change
      • Small, focused, decoupled components
      • Changes are localized, don't ripple
    • Safe to change
      • Tests catch regressions
      • Changes are reversible / version controlled
Well, if it is safe to change, then it is easy to change so these things are quite overlapping and connected, but this is what the big picture looks likes to me. Internal quality especially depends on your product and your team, so what "internal quality" means to your product should be discussed per product & team.

Custom RSS Generator

Apr 1, 2026

DIY
I wanted to read the Anthropic Engineering Blog through RSS. It does not support it. This is how I did it.

I use NetNewsWire to get all my daily news to consume. It is a free & high quality RSS / Atom reader.
Most blog sites provide an rss file, then it's as easy as just adding it in the UI in a matter of seconds. For Podcasts, most of them support rss so same thing.
For newsletters, I use the Kill the Newsletter! service to convert the newsletter into an RSS feed. For YouTube channels I want to get updates for, I use Inoreader to convert them into rss feeds, then add Inoreader as a folder in NetNewsWire.
Most things can be covered this way so that I get all my news in a singular space, which is what I need. But some blog sites just don't provide rss in which case I had no means to import their content. To solve this issue, you could use the Inoreader premium feature to create an rss feed from any page, but their auto-detection feature did not seem to be too sophisticated? (Not sure just fiddled shortly with it.)
The solution I cam up with was to just vibe code a custom scraper + rss generator with claude code that does the following
  1. Daily cronjob that regenerates the rss files (With an custom adapter per site)
  2. Serve the rss files on localhost:8888
Both are done with launchd since I am using a macbook. So launchd makes sure the rss files are served at all times, such as after reboots.
In the past, creating a custom adapter for each site would have been too much work so this would not have been viable. But now it's a matter of minutes, and once you've created it, you can keep getting information forever! (probaly not forever...) This also means that as long as you create this adapter, you're not limited to only blog sites, but you can import any kind of content you can imagine that has periodic update.
So, I finally could get updates for the Anthropic Engineering Blog through RSS! Hurray! At the end I noticed that the blog appearently now provides a developer newsletter monthly... Well that might have worked too through Kill the Newsletter!, but it is only monthly so some delay I presume and I am not sure if it is the same content so I am still happy with my solution. Especially that I now have almost no constraints to what I can read with RSS!

ไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹

Mar 28, 2026

meta-skill
ใ€Œไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ใ€ใฏใ„ใ„่จ€่‘‰ใ€‚ใ“ใ‚Œใฏใฉใ†ใ„ใ†ใ“ใจใชใฎใ‹ใ‚’่‡ชๅˆ†ใชใ‚Šใซ่จ€่ชžๅŒ–ใ™ใ‚‹ใ€‚
ใพใšใ€ไฝœใ‚‹ๅฏพ่ฑก็‰ฉใŒใ‚ใ‚‹ใ€‚ใ“ใ‚Œใฏ SaaS ใฎ Web ใ‚ขใƒ—ใƒชใชใฉใซ็›ธๅฝ“ใ™ใ‚‹ใ€‚ ใใ‚Œใ‚’๏ผˆ็›ดๆŽฅ๏ผ‰ไฝœใ‚‹่กŒ็‚บใฏไพ‹ใˆใฐไปฅไธ‹ใซ่ฉฒๅฝ“ใ™ใ‚‹ใ€‚
  • ็‰นๅฎšใฎ API ใ‚’ๅฎŸ่ฃ…
  • ็‰นๅฎšใฎใƒšใƒผใ‚ธใฎ UI ใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹
  • ่ฃใงใ‚ฌใƒใƒฃใ‚ฌใƒใƒฃๅ‹•ใใƒใƒƒใƒใ‚ธใƒงใƒ–ใ‚’ๅฎŸ่ฃ…ใ™ใ‚‹
ใชใฉใชใฉใ€‚
ใ“ใ‚Œใ‚‰ใฏๅฟ…่ฆใช่กŒ็‚บใงใ‚ใ‚Šใ€้ฟใ‘ใฆใฏ่ฃฝไฝœๅฏพ่ฑก็‰ฉใ‚’ๅฎŒๆˆใ•ใ›ใ‚‹ใ“ใจใฏใงใใชใ„ใ€‚ ใŸใ ใ€ใ”ใ‚Œใ‚‰ใฎ่กŒ็‚บใ‚’่กŒใ†้š›ใ€ไปฅไธ‹ใฎใ‚ˆใ†ใช่ชฒ้กŒ็‚นใซ่กŒใๅฝ“ใŸใ‚‹ใ“ใจใ‚‚ใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚
  • ใฉใ†ๅฎŸ่ฃ…ใ—ใŸใ‚‰ใ‚ˆใ„ใ‹ใ‚ใ‹ใ‚‰ใชใ„
  • ไป•ๆง˜ใŒๆ›–ๆ˜งใงใชใ‹ใชใ‹้€ฒใพใชใ„
  • ๅฎŸ่ฃ…ไธญใฎไธๆ˜Ž็‚นใŒๅ‡บใฆใใŸ้š›ใซใ€ใใ‚Œใ‚’ใƒใƒผใƒ ใจใ—ใฆ็›ธ่ซ‡ใƒป่งฃๆฑบใ™ใ‚‹ใพใงใฎใƒ—ใƒญใ‚ปใ‚นใŒๆ˜Ž็™ฝใงใฏใชใ„
  • ่‰ฒใ€…ใชๅฎŸ่ฃ…ใŒๅˆ†ๆ•ฃใ—ใฆใ„ใฃใฆใ„ใฆใ€ใฉใฎใƒ‘ใ‚ฟใƒผใƒณใซๅ€ฃใˆใฐใ„ใ„ใ‹ใ‚ใ‹ใ‚‰ใชใ„
ใ“ใ‚Œใ‚‰ใฏใ€Œไฝœใ‚‹ใ“ใจใ€่‡ชไฝ“ใฏใงใใฆใ„ใฆใ‚‚ใ€Œไฝœใ‚Šๆ–นใ€ใŒๆ˜Ž็™ฝใงใชใ‹ใฃใŸใ‚Šใ€่จ€่ชžๅŒ–ใ•ใ‚Œใ„ใชใ‹ใฃใŸใ‚Šใ€ใ‚ˆใ„ไฝœใ‚Šๆ–นใซๅŽๆŸใ—ใฆใ„ใชใ‹ใฃใŸใ‚Šใ™ใ‚‹ใŸใ‚ใซใŠใ“ใ‚‹ไบ‹่ฑกใงใ‚ใ‚‹ใ€‚ ใ€Œไฝœใ‚Šๆ–นใ€ใฏ๏ผ‘ใคใฎใ€Œไฝœใ‚‹ใ€่กŒ็‚บใงใฏใชใใ€ๆจชๆ–ญ็š„ใซใ™ในใฆใฎใ€Œไฝœใ‚‹ใ€ใ“ใจใฎ้€ฒใ‚ๆ–นใƒปๆ–นๆณ•่ซ–ใƒปใƒซใƒผใƒซใƒปใ‚ฌใ‚คใƒ‰ใƒฉใ‚คใƒณใ‚’ๆ็คบใƒปๅ…ฑๆœ‰ใ™ใ‚‹ใ‚‚ใฎใงใ‚ใ‚‹ใ€‚ ใใฎใŸใ‚ใ€ใ‚ณใ‚นใƒˆๅฏพๅŠนๆžœใŒ้žๅธธใซๅคงใใ„ใฏใšใ€‚
ใ€Œไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ใ€ไพ‹ใจใ—ใฆใฏไปฅไธ‹ใฎใ‚ˆใ†ใชใ‚‚ใฎใ‚’ๆƒณๅฎšใ—ใฆใ„ใ‚‹
  • Layered Architecture ใ‚’ๆŽก็”จใ—ใฆใ„ใ‚‹ใŒๅ„ๅฑคใฎ่ฒฌๅ‹™ใŒๆ›–ๆ˜งใงใ‚ใ‚Šใ€่ช่ญ˜ใŒใƒใƒผใƒ ๅ†…ใงใƒใƒฉใ‘ใฆใ„ใ‚‹ใ€‚ใ‚ฌใ‚คใƒ‰ใƒฉใ‚คใƒณใ‚’็ญ–ๅฎšใ—ใ€ใƒใƒผใƒ ๅ†…ใงๅ…ฑๆœ‰ใ™ใ‚‹ใ“ใจใงใƒ‘ใ‚ฟใƒผใƒณใฎ็ตฑไธ€ใธใจๅ‘ใ‹ใฃใฆใ„ใ‘ใ‚‹ใ€‚
  • ๆฉŸ่ƒฝ้–‹็™บใฎ้€ฒใ‚ๆ–นใจใ—ใฆใ€ใ–ใฃใใ‚Šใจใ—ใฆใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆ๏ผ‘ใคใŒๆธกใ•ใ‚Œใ€ใใ“ใ‹ใ‚‰ๅ››่‹ฆๅ…ซ่‹ฆใ—ใชใŒใ‚‰ใ‚จใƒณใ‚ธใƒ‹ใ‚ขใŒไป•ๆง˜ใƒป่ฆๆฑ‚ใ‚’ๆ˜Ž็ขบใซใ—ใชใŒใ‚‰้€ฒใ‚ใฆใ„ใŸใŒใ€่ฆๆฑ‚ใ‚’็›ดๆŽฅๆ‹พใ„ไธŠใ’ใฆใ„ใชใ„ใฎใงใ€้–‹็™บ็€ๆ‰‹ใพใงใŒ้…ใ‹ใฃใŸใ‚Šใ€็€ๆ‰‹ใ—ใฆใ‚‚ๆบ€ใŸใ™ในใ่ฆๆฑ‚ใŒๆ˜Ž็™ฝใ˜ใ‚ƒใชใ„ใพใพ้€ฒใ‚“ใงใ€ไฝ•ใ‹ใ‚’่งฃๆฑบใ™ใ‚‹ใ‚‚ใฎใงใฏใชใ„็Šถๆ…‹ใจใชใฃใฆใ—ใพใ†ไบ‹ๆ…‹ใชใฉใŒ่ตทใ“ใฃใฆใ—ใพใฃใฆใ„ใ‚‹ใ€‚ใใ“ใงใ€่‡ชๅˆ†ใ‚‰ใฎใƒ•ใ‚งใƒผใ‚บใซๅˆใ‚ใ›ใฆ้–‹็™บใƒ—ใƒญใ‚ปใ‚นๅ…จไฝ“ใฎๆง‹ๆƒณใ‚’็ทดใฃใฆใ€PdM ใชใฉใฎ่ฒฌๅ‹™ใ‚’ๆ˜Žใ‚‰ใ‹ใซใ—ใ€้‡่ฆใงใ‚ใ‚‹ใ€Œ่ฆๆฑ‚ใŒใ“ใ‚Œใงๆœฌๅฝ“ใซๆบ€ใŸใ›ใ‚‹ใ‹๏ผŸใ€ใชใฉใฎใŸใ‚ใฎ็‰นๅˆฅใช็ขบ่ชใ‚นใƒ†ใƒƒใƒ—ใ‚’่จญใ‘ใŸใ‚Šใ—ใฆใ€ๆฝคๆป‘ใ‹ใคๆ„็พฉใฎใ‚ใ‚‹้–‹็™บใŒใงใใ‚‹ใ‚ˆใ†ใซๆบ–ๅ‚™ใ‚คใƒณใ‚จใƒผใƒ–ใƒซใ™ใ‚‹ใ€‚
  • AI ้ง†ๅ‹•้–‹็™บใซใŠใ‘ใ‚‹ๅ„็จฎ่ชฒ้กŒ็‚นใ‚’ๆ”พ็ฝฎใ›ใšใ€ไป•็ต„ใฟๅŒ–ใงๅ›žๅŽใ—ใ€้€Ÿๅบฆใจๅˆถๅบฆใ‚’ๅ‘ไธŠใ•ใ›ใ‚‹ใ€‚ไพ‹ใˆใฐใ€CI ใŒๅคฑๆ•—ใ—ใฆไบบ้–“ใŒใ„ใคใ‚‚ใใฎๆฃŸใ‚’ใ‚จใƒผใ‚ธใ‚งใƒณใƒˆใซไผใˆใ‚‹ไผ่จ€่€…ใฎใ‚ˆใ†ใชๅฝนๅ‰ฒใ‚’ๆ‹…ใฃใฆใ„ใŸใชใ‚‰ใฐใ€ใ‚จใƒผใ‚ธใ‚งใƒณใƒˆใฎ็ต‚ไบ†ๆกไปถใง CI ใซ่ฟ‘ใ—ใ„ๆกไปถใ‚’็››ใ‚Š่พผใฟใ€่‡ชๅทฑๅฎŒ็ตๅž‹ใพใงใ‚‚ใฃใฆใ„ใใ“ใจใ€‚ใพใŸใ€AI ใ‚จใƒผใ‚ธใ‚งใƒณใƒˆใซใ‚ˆใ‚‹ไธๆญฃ็ขบใชไฟฎๆญฃใ‚„ๆฑบๅฎšใ—ใŸใƒ‘ใ‚ฟใƒผใƒณใซๆบ–ๆ‹ ใ—ใชใ„ๅฎŸ่ฃ…ใŒ็™บ็”Ÿใ—ใŸๅ ดๅˆใฏใ€ใใฎๅ ดใงใ ใ‘ไฟฎๆญฃใ™ใ‚‹ใฎใ‚’ใ‚„ใ‚ใฆใ€ๅ…จไฝ“ใฎ่จญๅฎšใƒ•ใ‚กใ‚คใƒซใฎๆ›ดๆ–ฐใ‚„ใƒชใƒณใ‚ฟใƒผใƒซใƒผใƒซใฎ่ฟฝๅŠ ใชใฉใฎๆ’ไน…ไฝœใซ็š†ใŒ็ฐกๅ˜ใซๅฏ„ไธŽใงใใ‚‹ใ‚ˆใ†ใชใ—ใใฟใ‚’ไฝœใ‚‹ใชใฉใ€‚
ใ“ใฎใ‚ˆใ†ใซใ€Œไฝœใ‚Šๆ–นใ€ใฏใ„ใคใ‚‚ๅ€‹ไบบใฎใƒฌใƒ™ใƒซใฎ่ฉฑใงใฏใชใใ€ใƒใƒผใƒ ใƒฌใƒ™ใƒซใฎ่ฉฑใซใชใ‚‹ใ€‚ ่‡ชๅˆ†ใฎใ€Œไฝœใ‚Šๆ–นใ€ใฎใ“ใจใงใฏใชใใ€ใ“ใฎ้–‹็™บใซ้–ขใ‚ใ‚‹ๅ…จใ‚นใƒ†ใƒผใ‚ฏใƒ›ใƒซใƒ€ใƒผใฎใ€Œไฝœใ‚Šๆ–นใ€ใ‚’ๆŒ‡ใ—ใฆใ„ใ‚‹ใ€‚ ใใ†ใชใ‚‹ใจใ€ใ€Œไฝœใ‚Šๆ–นใ€ใ‚’ไฝœใ‚‹ใŸใ‚ใซๅฟ…่ฆใชๆๆ–™ใจใ—ใฆไปฅไธ‹ใŒใ‚ใ‚Šใใ†ใงใ‚ใ‚‹ใ€‚
  • ่ชฒ้กŒใฎ็™บ่ฆ‹๏ผ‰ใ€Œไฝœใ‚Šๆ–นใ€ใŒๆฌ ๅฆ‚ใƒปๆœชๅฎŒๆˆใงใ‚ใ‚‹ใ“ใจใซใ‚ˆใ‚‹ๅ•้กŒ็‚นใ‚’่ช็Ÿฅใ—ใ€ๆœฌๅฝ“ใซๅ•้กŒใ‹ใ‚’ๅ…ฑๆœ‰ใ—ใฆๅ…ฑๅŒ่ช็Ÿฅใจใ™ใ‚‹ใ€‚
  • ๅฏพๅฟœใฎๆฑบๅฎš๏ผ‰ใฉใฎใ‚ˆใ†ใชใ€Œไฝœใ‚Šๆ–นใ€ใซใ™ใ‚Œใฐใ€ใใฎ่ชฒ้กŒใ‚’่งฃๆฑบใงใใ‚‹ใฎใ‹่€ƒๅฏŸใ™ใ‚‹ใ€‚ๅฎŸ้š›ใ‚„ใฃใฆใ„ใชใ„ใŸใ‚ไธ็ขบๅฎŸๆ€งใ‚‚้ซ˜ใ„ไธญใ€ไธ€ๆ–น้€š่กŒใชใฎใ‹ๅŒๆ–นๅ‘ใชใฎใ‹ใซใ‚ˆใฃใฆ็†Ÿ่€ƒๅบฆๅˆใ„ใ‚’่ชฟๆ•ดใ—ใ€ๅฏพๅฟœๆกˆใ‚’ๆฑบๅฎšใ™ใ‚‹ใ€‚
  • ๅ…ฑๆœ‰ใจๅฎŸๆ–ฝ๏ผ‰ๅพ—ใ‚‰ใ‚ŒใŸๅญฆใณใƒปๅฎŸๆ–ฝใ—ใŸใ„ๆ–ฐใ—ใ„ใ€Œไฝœใ‚Šๆ–นใ€ใ‚’ใƒใƒผใƒ ๅ†…ใงใ‚ใ‹ใ‚Šใ‚„ใ™ใๅ…ฑๆœ‰ใ—ใ€ๆ‡ธๅฟตใƒป่ฆณ็‚นใ‚’ๆ‹พใ„ไธŠใ’ใ‚‹ใ€‚ใใ‚Œใ‚’่ธใพใˆใฆ่งฃๆฑบ็ญ–ใ‚’็ทดใ‚‹็›ดใ—ใคใคใ€ๅฐŽๅ…ฅใ—ใฆใ„ใใ€‚
ใ‚‚ใ—ใ€ใ“ใฎใƒ—ใƒญใ‚ปใ‚นไบ‹ๆ…‹ใŒๅคš็™บใ—ใ€ใ‹ใคใ€ใŽใ“ใกใชใๆ„Ÿใ˜ใŸๅ ดๅˆใฏใ€ใ€Œไฝœใ‚Šๆ–นใฎไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ใ€ใจใ„ใ†ใ•ใ‚‰ใซใƒกใ‚ฟใชใ‚‚ใฎใซใคใ„ใฆไธ€ๅฎšๆ•ดๅ‚™ใ™ใ‚‹ใ“ใ‚‚ใจ่€ƒใˆใ‚‰ใ‚Œใ‚‹ใ€‚ ไพ‹ใˆใฐใ€ใƒใƒผใƒ ใงใฎ่ญฐ่ซ–ใ‚’็ตŒใฆใ‹ใ‚‰ใฎๆ„ๆ€ๆฑบๅฎšใ‚’่ฆใ™ใ‚‹้‡ๅคงใชไบ‹ๆŸ„ใจๅ€‹ไบบใŒๆ„ๆ€ๆฑบๅฎšใ—ใฆไบ‹ๅพŒๅ ฑๅ‘Šใซ็•™ใ‚ใ‚‹ใ‚‚ใฎใชใฉใ‚’ๅŒบๅˆฅใ™ใ‚‹ๆ–นๅผใ‚’ๆŽก็”จใ™ใ‚‹ใชใฉใฏใ“ใ‚Œใซใ‚ใŸใ‚‹ใงใ—ใ‚‡ใ†ใ€‚
็‰นใซ AI ใซใ‚ˆใ‚‹่‡ชๅ‹•ๅŒ–ใŒใชใ›ใ‚‹้ ˜ๅŸŸใŒๆ‹กๅคงใ—ใฆใ„ใ‚‹ไธญใ€ๅ…ทไฝ“็š„ใช้–‹็™บใ‚ˆใ‚Šใ‚‚ใ“ใฎใ‚ˆใ†ใชใƒ—ใƒญใ‚ปใ‚นๅŒ–ใƒปไป•็ต„ใฟๅŒ–ใƒปๅคงๅฑ€็š„ใชไฝœใ‚Šๆ–นใซใคใ„ใฆ่€ƒใˆใฆๅŠน็އๅŒ–ใ—ใฆใ„ใใ“ใจใŒ้‡่ฆใงใ‚ใ‚‹ใ“ใจใฏ่‡ชๆ˜Žใ ใ€‚ ใจใฏใ„ใˆใ€็ฌฌไธ€็ทšใงๆˆฆใ†็ตŒ้จ“ใŒ่–„ใ„ใจใ€ไฝœใ‚Šๆ–นใง่งฃๆฑบใ—ใ‚ˆใ†ใจใ™ใ‚‹็—›ใฟไบ‹ๆ…‹ใ‚’็Ÿฅใ‚‰ใชใ„ใ“ใจใซใชใ‚Šใ€ๆญฃใ—ใ„่ชฒ้กŒๆ„Ÿใ‚’ๆŒใฆใชใ‹ใฃใŸใ‚Šใ€่งฃๆฑบ็ญ–ใฎๆ–นใซๆฝœใ‚“ใงใ„ใ‚‹้š ใ‚Œใ‚ณใ‚นใƒˆใ‚’ๆŠŠๆกใงใใชใ‹ใฃใŸใ‚Šใ™ใ‚‹ใ“ใจใ‚‚ใ‚ใ‚‹ใงใ—ใ‚‡ใ†ใ€‚ ใใฎใŸใ‚ใ€ไธ€ๅฎšใ€Œไฝœใ‚‹ใ“ใจใ€ใ‚’ใ™ใ‚‹ใ“ใจใซใ‚ˆใฃใฆใ€Œไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ใ€ใ“ใจใ‚‚ใงใใ‚‹ใ‚ˆใ†ใซใชใ‚‹ใ‚“ใ ใ‚ใ†ใชใ€‚ใใฎๅกฉๆข…ใŒ้›ฃใ—ใ„ใŒใ€ใใ‚Œใฏไฝ•ไบ‹ใซใคใ„ใฆใ‚‚่จ€ใˆใ‚‹ใ€‚
ใพใŸใ€ใ‚ˆใ‚Šๆœชๆฅใซ็›ฎ็ทšใ‚’ๆƒใˆใ‚‹ใจใ€AI ใŒใ‚ฌใ‚คใƒ‰ใƒฉใ‚คใƒณใ‚„ๆ–น้‡ใฎๆ”นๅ–„ใ‚’่‡ช็ซ‹็š„ใซๆŽจ่–ฆใ™ใ‚‹ใ‚ˆใ†ใซใชใฃใฆใใ‚‹ใจใ€ๆฌกใฏๆœฌๅฝ“ใซใใ‚Œใ‚‰ใฎใ€Œไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ใ€่กŒ็‚บใฎใƒฌใƒ“ใƒฅใƒผใ‚’ใ—ใŸใ‚Šใ€ๅˆถๅพกใ—ใŸใ‚Šใ™ใ‚‹ใฎใงๆœฌๅฝ“ใซใ€Œไฝœใ‚Šๆ–นใ‚’ไฝœใ‚‹ไฝœใ‚Šๆ–นใ€ใฟใŸใ„ใชใ‚ˆใ‚ŠไธŠไฝใงใ‚ใ‚Šใƒกใ‚ฟใช้–‹็™บ่กŒ็‚บใซใชใฃใฆใ„ใใฎใ‹ใญใ€ใ€ ไบบ้–“ใฏใฉใ“ใพใงใฎๆŠฝ่ฑกๅบฆใซ่€ใˆใ‚‰ใ‚Œใ‚‹ใฎใ ใ‚ใ†ใ‹ใ€‚ๅ…ทไฝ“ใ‚’็Ÿฅใ‚‰ใชใ„ใพใพๆŠฝ่ฑกๅบฆใ ใ‘ไธŠใŒใฃใฆใ„ใฃใฆใŸใ‚‰ใ€ๅพใ€…ใซๅคขใ‚„้ญ”ๆณ•ใฎไธ–็•Œใซๅ‘ใ‹ใฃใฆใ„ใใ€‚ ใ‚‚ใกใ‚ใ‚“ใ„ใพใพใงใ‚‚ๆŠฝ่ฑกๅบฆใ‚’ไธŠใ’ใฆใใŸใ€‚0101 ใ‹ใ‚‰ใ‚ขใ‚ปใƒณใƒ–ใƒชใ‹ใ‚‰้ซ˜็ดš่จ€่ชžใพใงใจใ‹ใ€‚ไปŠๅ›žใ‚‚ๅŒใ˜ใ‚ˆใ†ใชใŸใŸใฎ๏ผ‘ใ‚นใƒ†ใƒƒใƒ—ใชใฎใ‹ใ€ใ‚‚ใฃใจๆ€ง่ณชใŒ้•ใ†ใ‚‚ใฎใชใฎใ‹ใ€้•ใ†ๆฐ—ใŒใ™ใ‚‹ใ€ใ€ใพใŸๅˆฅใฎๆฉŸไผšใซ่€ƒๅฏŸใ—ใ‚ˆใ†ใ€‚

Created a tmux plugin for claude code

Mar 27, 2026

claude code
tmux
Today, I created a tmux plugin to list all claude sessions, and jump to their respective tmux windows.
I use tmux extensively with many sessions and windows existing at the same time. Also, I use claude code a lot resulting in many claude code session dispersed across many tmux sessions / windows. As a result, I often had a hard time tracking which claude code session is still running, what is done and what requires additional input.
Futhermore, I have it setup such that I get notified with a sound when claude code has completed or requires permissions. But when I run multiple claude code sessions, I had a hard time figuring out where to go, which caused some friction in my development process.
My tailored solution was to create a plugin that utilizes tmux-fzf, a tmux plugin that can have a floating pane where you can fuzzy find, and list all running claude code sessions & their respective states (completed, waiting, running) shown. Also, it allows me to attach to that specific tmux window that runs it. Not with one stroke I open this pane, can confirm the total state, and then jump directly to wherever I need to be.
tmux-claude-picker plugin
Shared it with some coworkers and they seem to enjoy it too!

We become what we think about

Mar 24, 2026

mindset
Recently I think about this phrase from Earl Nightingale a lot. "We become what we think about". This implies that our thoughts shape what we become.
If you think about failure every day, you're likely to fail. If you think about becoming a great engineer every day, you move in that direction. If you do NOT think about that every day, it won't gonna happen miraculously.
It makes sense to me. If you think about something everyday, you will have many opportunities to think about it, and that gives you many chances to take smaller steps directed towards it. In contrast when something is out of your mind, you'll most likely forget about it and when you remember it, months and years will have past. If just that thing was in your center of focus, you'd have lived such as different life.
It shows how important it is to control and direct your thoughts, especially the core parts. Any great goal, is not achieved in a day. It is the accumulation of what you do on a daily. So governing the daily you, is what enables you to steer yourself conciously.
One way you can do that is to do with journaling and reflection on the daily. More is not always better, if you have 10 things you want to be, that dillutes and often nothing remains. For me, pick only one thing and focus on that. And only once that is fully incoroporated into your focus, should you move on to incoroporate other things.
We become what we think about, so think about what you want to become.

Anti Corruption Layer (ACL) / ่…ๆ•—้˜ฒๆญขๅฑค

Mar 19, 2026

DDD
DDD ใซใŠใ„ใฆ่…ๆ•—้˜ฒๆญขๅฑคใจใ„ใ†ๅคงๅฑคใชๅๅ‰ใฎใ‚‚ใฎใŒใ‚ใ‚‹ใ€‚ ใ™ใ”ใ้‡่ฆใงใ‚ใ‚Šใ€ใ ใ‹ใ‚‰ใ“ใๅคงๅฑคใชๅๅ‰ใ‚’ใคใ‘ใฆใ„ใ‚‹ใฎใ ใจๆ€ใฃใŸใ€‚
ๅฎŸ่ณชๅค‰ๆ›่กŒใ† "ใ ใ‘" ใฎๅค–้ƒจใจๅ†…้ƒจใฎ้–“ใ‚’ๅ–ใ‚ŠๆŒใคไธ€็จฎใฎใ€Œๅฑคใ€ใงใ‚ใ‚‹ใ€‚ ๅ†…้ƒจใจใฏ DDD ใซๅŸบใฅใ„ใฆๅฎŸ่ฃ…ใ—ใฆใ„ใ‚‹่‡ชๅˆ†ใ‚‰ใฎใƒ‰ใƒกใ‚คใƒณใƒขใƒ‡ใƒซใฎใ“ใจใงใ‚ใ‚‹ใ€‚ ๅค–้ƒจใจใฏ้€ฃๆบใ—ใฆใ„ใ‚‹ใƒฌใ‚ฌใ‚ทใƒผใ‚ทใ‚นใƒ†ใƒ ใ‚„ไป–็คพใฎ API ใชใฉใงใ‚ใ‚‹ใ€‚ ใ“ใ‚Œใ‚‰ใฎๅค–้ƒจใฎ้ƒฝๅˆใซใคใ‚‰ใ‚Œใฆใ€ใƒ‰ใƒกใ‚คใƒณใƒขใƒ‡ใƒซใงๅŒใ˜ใ‚ˆใ†ใช่กจ็พใ‚’ใ—ใฆใ„ใŸใ‚‰ใ€ๅ…ƒใ‚‚ๅญใ‚‚ใชใ„ใ€‚ ๅค–้ƒจใฎ้ƒฝๅˆใงใฏใชใใ€ใƒ‰ใƒกใ‚คใƒณใƒขใƒ‡ใƒซใจใ—ใฆใฉใ†ใ‚ใ‚‹ในใใซๅŸบใฅใ„ใฆใƒขใƒ‡ใƒชใƒณใ‚ฐใ—ใ€ๅฎŸ่ฃ…ใ—ใŸใ„ใ€‚ ใใ‚Œใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏ็‹ฌ็ซ‹ๆ€งใŒๅฟ…่ฆใงใ‚ใ‚‹ใ€‚็‹ฌ็ซ‹ๆ€งใ‚’ๅฎŸ็พใ™ใ‚‹ใซใฏใ€ๅ†…้ƒจใจๅค–้ƒจใฎ้–“ใ‚’ใ‚ˆใ—ใชใซใ—ใฆใใ‚Œใ‚‹ใ‚‚ใฎใŒๅฟ…่ฆใงใ€ใใ‚ŒใŒใ€Œ่…ๆ•—้˜ฒๆญขๅฑคใ€ใซ็›ธๅฝ“ใ™ใ‚‹ใ€‚
่…ๆ•—้˜ฒๆญขๅฑคใฎ่ฉฑใ‚’ใ™ใ‚‹ใจ Adapter, Facade, Translator ใŒๅ‡บใฆใใ‚‹ใ€‚ใ“ใ‚Œใ‚‰ใฏใชใ‚“ใžใ‚„๏ผŸ
ใ“ใ‚Œใ‚‰ใŒ่งฃๆฑบใ™ใ‚‹ๅ•้กŒใ‚’่ฆ‹ใ‚ˆใ†ใ€‚ๅค–้ƒจใฎ้ƒฝๅˆใซๅผ•ใใฅใ‚‰ใ‚Œใ‚‹ใจๅ›ฐใ‚‹ๅ•้กŒใจใ—ใฆไปฅไธ‹ใŒใ‚ใ‚‹ใ€‚
  • ๅž‹ใ€่กจ็พๅฝขๅผใ€ๅˆถ็ด„ใ€ๅ‘ฝๅใชใฉ๏ผˆไธ€็•ชๅˆ†ใ‹ใ‚Šใฅใ‚‰ใ„้ƒจๅˆ†๏ผ‰
  • ๆไพ›ใ•ใ‚Œใฆใ„ใ‚‹ใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚น๏ผˆAPI๏ผ‰ใฎ็ฒ’ๅบฆ๏ผˆ้€ฃๆบๅ…ˆใฏใฎ๏ผ“ใคใฎๅ–ๅพ— API ใงใ‚„ใฃใจๆˆ‘ใ€…ใŒใปใ—ใ„๏ผ‘ใคใฎใƒ‡ใƒผใ‚ฟใŒๅพ—ใ‚‰ใ‚Œใ‚‹ใชใฉ๏ผ‰
ใ“ใฎๅ•้กŒใ‚’่งฃๆถˆใ™ใ‚‹ใฎใŒไปฅไธ‹
  • Translator -> ็ฟป่จณใ‚’ๆ‹…ใ†ใƒ‘ใƒผใƒ„ใ€‚ๅค‰ๆ›ใจ่žใ„ใŸใ‚‰ไธ€็•ชใซๆ€ใ„ๆตฎใ‹ใถใจใ“ใ‚ใ€‚
  • Facade -> ใ“ใ‚Œใฏใ€Œ่ฆ‹ใ›ใ‹ใ‘ใ€ใ€Œไปฎ้ขใ€ใชใฉใ‚’ๆ„ๅ‘ณใ™ใ‚‹ๅ˜่ชžใงใ‚ใ‚‹ใ€‚ใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใŠใฎ็ฒ’ๅบฆใ‚’่‡ชๅˆ†ใ‚‰ใฎ้ƒฝๅˆใฎใ‚ˆใ†ใ‚ˆใ†ใซ่ฆ‹ใ›ๆ–นใ‚’ๆ›ฟใˆใ‚‹ใƒ‘ใƒผใƒ„ใ€‚
ใพใŸใ€ๅค–้ƒจใงใฏ REST API ใงใ‚ใฃใŸใ‚Š SOAP API ใงใ‚ใฃใŸใ‚Š XML ใ‚’่ฟ”ใ—ใŸใ‚Š JSON ใ‚’่ฟ”ใ—ใŸใ‚Šใงใ€ใใ‚Œใ‚‰ใฎ้ƒฝๅˆใ‚‚ใฉใ“ใ‹ใงๅธๅŽใ—ใŸใ„ใ€‚
ใงใใฎๅ•้กŒใ‚’่งฃๆถˆใ™ใ‚‹ใฎใŒ Adapterใ€‚
ใ“ใ‚Œใ‚‰ใ‚’็ต„ใฟๅˆใ‚ใ›ใฆไปฅไธ‹ใฎใ‚ˆใ†ใชใ€Œ่…ๆ•—้˜ฒๆญขๅฑคใ€ใŒๆง‹ๆˆใงใใ‚‹ใ€‚๏ผˆๆ–‡ๅญ—ใŒใกใ‚‡ใ„ๅฐใ•ใ„ใŒใ€ใ€๏ผ‰
Anti Corruption Layer
ใƒ‰ใƒกใ‚คใƒณใฎ่กจ็พใจๅค–้ƒจใฎ่กจ็พใฎ้–“ใซใ€Œ่…ๆ•—้˜ฒๆญขๅฑคใ€ใŒใ‚ใ‚Šใ€ใใ‚ŒใŒๆ›ดใซ๏ผ“ใคใฎใ‚ตใƒ–ๅฑคใ‹ใ‚‰ใชใฃใฆใ„ใ‚‹ใ€‚ Adapter ใงใƒ•ใ‚กใ‚คใƒซๅฝขๅผใ‚„ใƒ—ใƒญใƒˆใ‚ณใƒซใฎ้•ใ„ใ‚’ๅธๅŽใ—ใ€Facade ใงใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใƒปAPIใฎ็ฒ’ๅบฆใฎ้•ใ„ใ‚’ๅธๅŽใ—ใ€Translator ใงใƒ•ใ‚ฃใƒผใƒซใƒ‰ใฎๅž‹ใƒปๅ€คใƒปๅ‘ฝๅใƒปๆง‹้€ ใชใฉใ‚’ๅค‰ๆ›ใ—ใฆใ€ใคใ„ใซๆˆ‘ใ€…ใŒใƒ‰ใƒกใ‚คใƒณ่กจ็พใซ่‡ณใ‚‹ใ€‚
ๅ€‹ไบบ็š„ใซใฏ Facade ใฎใจใ“ใ‚ใŒไธ€็•ช้ข็™ฝใๅญฆใณใŒๅคšใ„ใจใ“ใ‚ใงใ‚ใฃใŸใ€‚ Adapter ใจ Translator ใฎๆ–นใŒ่กŒใฃใฆใ„ใ‚‹ๅ‡ฆ็†ใซใคใ„ใฆใฏใ€ใพใ‚ๅฟ…่ฆใ ใ‚ใ†ใชใจๆ€ใฃใฆใ„ใŸใŒใ€Facade ใงใ‚ใƒผ่‡ชๅˆ†ใ‚‰ใฎ้ƒฝๅˆใซๅˆใ‚ใ›ใฆใ‚คใƒณใ‚ฟใƒผใƒ•ใ‚งใƒผใ‚นใฎ็ฒ’ๅบฆใ‚’่ชฟๆ•ดใ™ใ‚‹ใฎใ‹๏ผใจใ„ใ†็‚นใฏ้ข็™ฝใ‹ใฃใŸใ€‚ ใ‚ใจใฏ็ด”็ฒ‹ใซ Facade ใจใ„ใ†ใƒฏใƒผใƒ‰ใƒใƒงใ‚คใ‚นใŒใ‚คใ‚ฑใฆใ„ใ‚‹ใ€‚
ใ“ใ‚Œใง ACL ใฎๅˆๆญฉใฏๆŽดใ‚ใŸใฎใงใฏใชใ„ใ ใ‚ใ†ใ‹ใ€‚

Feature Document ใ‚’ไฝฟใฃใฆใ‚ปใƒƒใ‚ทใƒงใƒณ้–“ใงใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹

Mar 18, 2026

AI ้ง†ๅ‹•้–‹็™บ
Claude Code
ๅคงใใ‚ใฎๆฉŸ่ƒฝใ‚’้–‹็™บใ™ใ‚‹ใจใใ€ใ‚‚ใ—ใใฏ CLEAN ใ‚ขใƒผใ‚ญใƒ†ใ‚ฏใƒใƒฃใ‚’ๆŽก็”จใ—ใฆใ„ใฆ๏ผ‘ใคใฎๆฉŸ่ƒฝ้–‹็™บใŒ่ค‡ๆ•ฐใฎใƒฌใ‚คใƒคใƒผใฎใ‚ตใƒ–ใƒใ‚ฑใƒƒใƒˆใซๅˆ†ๅ‰ฒใ•ใ‚Œใฆใ„ใ‚‹ใจใใซใ€่ค‡ๆ•ฐใฎ Claude Code ใ‚ปใƒƒใ‚ทใƒงใƒณใงๅฎŸ่ฃ…ใ™ใ‚‹ใ“ใจใซใชใ‚‹ใ€‚ ใ“ใฎใจใใ€ใใฎใ‚ปใƒƒใ‚ทใƒงใƒณ้”ใŒ้‡่ฆใชๆƒ…ๅ ฑใ‚’ๅ…ฑๆœ‰ใ™ใ‚‹ใŸใ‚ใฎๆœ‰ๅŠนใชๆ‰‹ๆฎตใŒใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใงใฏใชใ„ใ€‚ Claude ใซใฏ Auto-memory ใจใ„ใ†ๆฉŸ่ƒฝใŒใ‚ใ‚Šใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใƒฌใƒ™ใƒซใง้‡่ฆใชใ“ใจใ‚’่‡ชๅ‹•ใง่จ˜ๆ†ถใ—ใฆใใ‚Œใ‚‹ๆฉŸ่ƒฝใ‚‚ใ‚ใ‚‹ใŒใ€ๆฉŸ่ƒฝใƒฌใƒ™ใƒซใ ใจๅŸบๆœฌ็š„ใซใฏใชใ„ใ€‚ ใใ“ใงใใฎๆฉŸ่ƒฝใซใพใคใ‚ใ‚‹้‡่ฆใชๆฑบใพใ‚Šใ”ใจใ‚’ๆฏŽๅ›ž่ชฌๆ˜Žใ™ใ‚‹ใฎใ‚‚ๅ„„ๅŠซใงใ‚ใฃใŸใ‚Šใ€ไป–ใฎๆ–นใจๅˆ†ๆ‹…ใ—ใฆๅฎŸ่ฃ…ใ™ใ‚‹ๅ ดๅˆใ‚‚ใใฎๆฑบใพใ‚Šใ”ใจใŒๆญฃใ—ใๅ…ฑๆœ‰ใ•ใ‚Œใฆใ„ใชใ‹ใฃใŸใ‚Šใฎๅ•้กŒใŒ็™บ็”Ÿใ™ใ‚‹ใ€‚
ใ“ใฎใ‚ˆใ†ใชๅ•้กŒใฎๅฏพๅ‡ฆๆณ•ใจใ—ใฆ Feature Document ใจใ„ใ†้ธๆŠž่‚ขใ‚’็ŸฅใฃใŸใ€‚ Feature Document ใฏๆฉŸ่ƒฝใฎๅฎŸ่ฃ…ๆœŸ้–“ใ ใ‘็”Ÿๅญ˜ใ™ใ‚‹ใƒ‰ใ‚ญใƒฅใƒกใƒณใƒˆใงใ‚ใ‚‹ใ€‚ ๆฉŸ่ƒฝใฎ้‡่ฆใชๆฑบใพใ‚Šใ”ใจใ‚’่จ˜่ผ‰ใ—ใ€ๅ„ใ‚ปใƒƒใ‚ทใƒงใƒณใง่ชญใฟ่พผใ‚ใ‚“ใงๅ…ฑๆœ‰ใ—ใ€ๅฎŸ่ฃ…ไธญใฎ่ฟฝๅŠ ๆฑบๅฎšไบ‹้ …ใŒใ‚ใ‚Œใฐใ€ใใฎๅ ดใงๆ›ดๆ–ฐใ‚‚ใงใใ‚‹ใ€‚
ๅ…ทไฝ“็š„ใซใฏใ€ใƒฌใƒใ‚ธใƒˆใƒชใฎใฉใ“ใ‹ใซ้…็ฝฎใ—ใฆ git ใซใƒใ‚งใƒƒใ‚ฏใ‚คใƒณใ—ใฆใ‚‚ใ„ใ„ใŒใ€่‡ชๅˆ†ใฏใพใšใฏ่ฉฆ้จ“็š„ใซไฝฟใ†ใŸใ‚ใซไปฅไธ‹ใฎ่จญๅฎšใ‚’ไฝฟใฃใŸใ€‚
  • ~/feature_documents/ ใƒ‡ใ‚ฃใƒฌใ‚ฏใƒˆใƒชใ‚’ไฝœใ‚‹
  • ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆใฎ CLAUDE.local.md ใซไปฅไธ‹ใฎใ‚ˆใ†ใชๆŒ‡็คบใ‚’่ฟฝ่จ˜ใ—ใ€ๆฉŸ่ƒฝ้–‹็™บๆ™‚ใซ่‡ชๅ‹•ๅ‚็…งใ™ใ‚‹ใ‚ˆใ†ใซ
When doing any kind of feature implementation, look at `~/feature_documents/` to see if there are any relevant feature documents.
If available, read that document and follow its instructions.
Also, if new decisions have been made about the feature or how to implement it that are specific to that feature, then update the document.
 
File format is `<date>-<content>` e.g. `2026-03-18-add-fuzzy-search`
ๆœฌๆฅใฏใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆ็‰นๅŒ–ใฎๆƒ…ๅ ฑใฎใŸใ‚ใ€ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆไป˜่ฟ‘ใซใŠใใฎใŒๅฅฝใพใ—ใ„ใŒใ€ใพใšใฏ่ฉฆ้จ“็š„ใซๅฐŽๅ…ฅใจใ„ใ†ใ“ใจใงใ“ใฎใ‚ˆใ†ใซใ—ใŸใ€‚ ๅ€‹ไบบใฎ Claude ๆจฉ้™ ~/.claude/settings.json ใซใŠใ„ใฆใ“ใฎใƒญใ‚ฑใƒผใ‚ทใƒงใƒณใฎ่ชญใฟๆ›ธใๆจฉ้™ใ‚’่ฟฝ่จ˜ใ—ใ€ๆจฉ้™่จฑๅฏใ‚’่žใ‹ใ‚Œใชใ„ใ‚ˆใ†ใซใ‚‚ใ—ใŸใ€‚
ใ“ใ‚Œใงใ€ใ‚ใ‚Šใจใ†ใพใ„ๅ…ทๅˆใซใ€ๅŒไธ€ใฎๆฉŸ่ƒฝ้–‹็™บใซๅฑžใ™ใ‚‹ใ‚ปใƒƒใ‚ทใƒงใƒณ้–“ใงๆƒ…ๅ ฑใƒปใ‚ณใƒณใƒ†ใ‚ญใ‚นใƒˆใ‚’ๅ…ฑๆœ‰ใงใใ‚‹ใ‚ˆใ†ใซใชใฃใŸใ€‚ ไฝฟ็”จใ—ใฆใ„ใฃใฆใ€ใพใŸ็Ÿฅ่ฆ‹ใŒใ‚ใ‚Œใฐ่จ˜่ผ‰ใ™ใ‚‹ใ€‚
ใ‚ฝใƒผใ‚น๏ผ‰martinFowler.com - Context Anchoring