{"slug": "i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday", "title": "I spent a week teaching my Mac app to remember what I meant last Tuesday", "summary": "A developer building Deiko, a Mac app that turns on-screen pointing and speech into briefs for coding agents, added a memory layer that groups related briefs so agents retain context across sessions. The system uses TypeSafe AI's Jev model, accessed via Vercel AI Gateway, OpenRouter and Cloudflare after TypeSafe paused direct signups, to score whether a new brief belongs to an existing task at roughly a tenth of a cent per brief. The design favors exact clues like the page or file being viewed over fuzzy model classification, and avoids re-learning injected context after observing a memory tool that saved the same memory 808 times.", "body_md": "[This happens to me about four times a day.](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%2F7pfbnsce7fdw7d6yhk3g.png)\n\nI find a bug. I explain it to my coding agent. We fix half of it. Three days later the other half turns up, and I'm explaining the whole thing again from scratch to an agent with the memory of a goldfish.\n\n\"No, not *that* price. The one on the pricing page. Remember? We tried the cache thing? It didn't work?\"\n\nIt doesn't remember correctly.\n\nSo last week I gave my app a memory. This post covers that week: how I stumbled onto Jev, the homework I did on how other apps remember things, the moment my own board embarrassed me, and the small filing algorithm I ended up with.\n\nDeiko is a Mac app I'm building. You double-tap a key, point at things on your screen and talk. Deiko turns that into a brief: your words, screenshots of what you pointed at, and the exact text that was on screen. Then you drag it onto Claude Code, Cursor or whatever agent you use, and it gets pasted in.\n\nEvery brief also lands on a board. That board is where the problem was hiding.\n\nAfter a few weeks of use, my board was a pile. Eleven briefs from one design demo sat there as eleven loose cards. Three briefs about the same $99 price bug had, as far as Deiko knew, nothing to do with each other.\n\nEach brief knew everything about its own moment and nothing about the one before it. What I wanted was easy to say:\n\nTalk about the same bug on Tuesday and on Friday. Deiko knows it's the same bug, and Friday's agent knows what Tuesday's agent already tried.\n\nEasy to say, anyway.\n\nJev kept turning up on my X feed. It's a model from TypeSafe AI that does one narrow thing oddly well: you give it some facts and a typed question like \"is this X?\", and it gives you back a probability. You don't get an essay or a \"Great question!\", just a number.\n\nThat's exactly the shape of my problem. \"Does this new brief belong to that old task?\" is a yes/no question with a confidence attached. It's also cheap: TypeSafe's docs list $0.042 per million input tokens, and output is free. Sorting one brief costs me about a tenth of a cent.\n\nSo I went to sign up, full of momentum, and got this:\n\nWhoops, we're full - check [https://x.com/typesafeai](https://x.com/typesafeai) for more information!\n\nThey had paused signups two days after opening them. Cool. Great. Love that for me.\n\nLuckily the same model is resold at the same price through a few gateways, so I wired in Vercel's AI Gateway, OpenRouter and Cloudflare, and the week carried on.\n\nBefore writing any code I did the thing I usually skip: I read how other tools remember things. I skipped the landing pages and read the mechanisms: the docs, the source where I could, and the GitHub issues where people complain.\n\n| Where I looked | What I took | \n|---|---|\n| Claude Code's memory, Cursor's memories | Keep one running note per piece of work, with \"where it stands now\" at the top and a hard size cap | \n| Mem0, Letta, Zep | Tools that classify every memory from scratch get the most \"why did it merge these?!\" complaints. Use cheap, exact clues first, and ask a model only when it's actually ambiguous | \n| Obsidian, Notion, Granola | When a person files something by hand, that choice is final | \n| Gmail threading | Exact clues beat fuzzy guesses. Email has a reply header; Deiko has the page or file you were looking at | \n| Sentry's issue grouping | Clean up an error before you match it, so \"line 42\" and \"line 43\" count as the same crash | \n| Search engines | Blend keyword search with meaning search, because each one catches what the other misses | \n\nOne bug report stayed with me: a memory tool had saved the same memory 808 times, because it kept re-learning whatever it had just put into the prompt. Lesson noted: never learn back what you injected.\n\n**v1: chains.** Each brief pointed at the one it continued. The result looked like beads on a string, and it barely helped. The eleven demo briefs were still eleven cards.\n\n**v2: tasks.** Now a brief belongs to a task, and a task belongs to a project. Deiko keeps a note for each task: where it stands, what was decided, what was tried. When the agent finishes, it writes its outcome back into that note. To pick the task, I showed Jev a shortlist of 8 and asked \"which one is this most like?\"\n\nI shipped it, re-sorted my real board and opened it up feeling rather proud.\n\nWhen I dug in, every mistake was mine, not Jev's.\n\nI was giving Jev a multiple-choice quiz when it's at its best with yes or no.\n\nv3 files a brief the way a careful librarian files a note.\n\n**1. Is it a note at all?** Jev answers \"is this a real request?\" Mic checks, greetings and thank-yous go to a pile called *mic checks & scraps*.\n\n**2. Read the labels.** Before any AI gets involved, Deiko reads exact labels off what it already recorded: the page, the file, the project, the error, the ticket number. Each one is tidied so two visits match. \"(3) Signups — build\" becomes \"Signups\". \"/users/8812\" becomes \"/users/*\". An error loses its line number (thanks, Sentry). Titles that don't name a real page, like \"New Tab\" or \"Dashboard\", don't count.\n\n**3. Cast a wide net.** Up to 20 tasks get a seat at the table:\n\n`index.tsx`.\nRecency gets no seats any more. It only breaks ties.\n\n**4. Ask yes or no, once per task.** In one request, Jev answers \"is this the same piece of work?\" for each of the 20 tasks. Every task gets its own probability, and they don't have to add up to 100%. The question says plainly that the same app or the same topic isn't enough.\n\n**5. Look twice at the finalists.** The one or two tasks that scored 35% or more each get a private second request containing just the new brief and that one task, so nothing else can sway the answer. It asks the same question again, plus one more: are these different, related but separate, or the same work?\n\n**6. Decide in boring code.** Jev only gives numbers. The rules that turn numbers into decisions live in my code, in one place, with tests:\n\n``` js\nexport const GATE = 0.5;  // below this, it's a mic check\nexport const JOIN = { first: 0.6, second: 0.4, gap: 0.2, recent: 0.5, recentMs: 30 * 60e3 };\nexport const ASK = 0.35;  // between this and a join: ask the human\n```\n\nMy design doc said \"join when the second look is 90% sure\". Sensible and principled.\n\nIt joined nothing. Zero briefs.\n\nBefore building v3 I had made a test set from my own board: real briefs, each labelled by hand with where it belongs. Every change had to beat the previous run. On the ten briefs that truly belonged together, Jev's one-on-one \"yes\" sat between 0.43 and 0.88. It said \"same\" every single time. It just wouldn't say it loudly. Meanwhile, every brief that really was new had its best match at 0.23 or lower.\n\nSo the numbers in that snippet came from my data, not from a hunch. If you take one thing from this post, make it this: **build the test set first.** I was confidently and completely wrong about the thresholds.\n\nWhere it stands now: 28 of the 33 labelled briefs land where I'd put them by hand, and about one real brief in nine gets a \"Which one?\" card. I watch that second number closely. If it creeps past one in four, people start clicking anything to make the card go away, and then memory is worse than no memory.\n\nFiling will sometimes be unsure, so the agent shouldn't have to depend on a single guess.\n\nWhen a brief joins a task, the agent is told: *this carries on from \"Pricing display bug\"*, where it stands, and the last few briefs, one line each. When it's only a hunch, the prompt says so: *possibly related, not confirmed*. The whole memory section stays under 20 lines.\n\nThere's also a small memory helper, an MCP server that runs only on your Mac, with three tools: `search_briefs`, `get_task` and `get_brief`. Say \"like the chart thing from last week\" and your agent can go and find it itself. One button in Settings sets it up for every agent Deiko finds on your Mac.\n\nThe search covers everything on your Mac, but it hands back much less, because the answers go to your agent's cloud model. You get your briefs, the agents' notes and the screenshots you kept. Screenshots you removed stay removed, audio never leaves, and anything that looks like a secret is scrubbed first. That last rule isn't hypothetical: our security audit once found a live API key in text Deiko had captured from the screen.\n\nOn Thursday you point at the pricing page and say \"the price still shows $99 after I edit it\". Your agent tries a cache fix. On Monday you point at the same page: \"still broken.\"\n\nDeiko files Monday's brief under *Pricing display bug*. Monday's agent gets the note saying the cache fix was tried and didn't work, so it starts from there instead of from zero. You didn't have to explain anything twice.\n\nDeiko runs on macOS 14 or later, and Pro is free until 24 October 2026.\n\n```\ncurl -fsSL https://deiko.app/install.sh | sh\n```\n\nThe site if you want more info -\n\nIf you've built memory for anything, I'd love to hear what broke for you, and which of my thresholds you think will age worst. Leave a comment below.", "url": "https://wpnews.pro/news/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday", "canonical_source": "https://dev.to/maddy30445r/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday-369c", "published_at": "2026-09-25 22:48:31+00:00", "updated_at": "2026-09-25 23:00:03.227377+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "large-language-models", "developer-tools"], "entities": ["Deiko", "Jev", "TypeSafe AI", "Vercel AI Gateway", "OpenRouter", "Cloudflare", "Claude Code", "Cursor"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday", "markdown": "https://wpnews.pro/news/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday.md", "text": "https://wpnews.pro/news/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday.txt", "jsonld": "https://wpnews.pro/news/i-spent-a-week-teaching-my-mac-app-to-remember-what-i-meant-last-tuesday.jsonld"}}