› the login tests have been failing since yesterday. find out why and fix it ● wave spawn explore · where is the session token validated? src/auth/session.ts:42 compares expiresAt in seconds with Date.now() in ms ● bash $ npm test -- auth ✗ login › keeps the session for 30 days expected true, received falseexpiresAtis in seconds andDate.now()in milliseconds, so every session looks expired. Fixing it insession.ts:42and running the tests again. ● edit src/auth/session.ts - if (session.expiresAt < Date.now()) return null; + if (session.expiresAt * 1000 < Date.now()) return null; ▁▃▅▇█ working 14s · esc to interrupt add a test for sessions in seconds claude-opus-5-5 · high · ctx 6.2%/400k · $0.412 · ↑38k ↓4.1k · cache 93% · ⏵ 1 current · ≋ explore · ~/Projects/app
Vocabulary
tide works in parallel and names each piece after the sea. The model and the interface use the same words.
- ≋wavea subagent
- Another conversation, with its own context and tools, that hands back only its conclusion. Runs in the foreground or background, on the model and thinking level you ask for: “use waves with haiku”.
- ⏵currenta background process
- A dev server, a build or the tests running while the session goes on. Ctrl+B sends the running command there. When it ends, the result reaches the model.
- ∿surfweb search
- Searches with Exa, no key needed.
web_fetchreads HTML pages and PDFs and returns clean markdown. - ›steer, follow-uptalking to a run
- A steer enters the running run at its next step. A follow-up waits for it to end. Reports from currents and waves arrive as follow-ups.
What it does
Three features set tide apart. The rest is what any coding agent needs.
Sessions that survive a crash
Each session is a SQLite file. Kill the terminal mid-run and tide picks the run back up when it opens. Come back after a break and a short recap says where things stand. tide -c continues, tide -r picks one.
$ tide -c ※ recap Fixed the seconds/milliseconds bug in session.ts and the auth tests pass. Next: a test for sessions stored in seconds.
/goal, until it's done
Give it a goal and tide works run after run. After each one, an Opus judge reviews the work and says what is missing, until the goal is met or a cap on runs or cost is hit.
› /goal every test passes and lint is clean … · ◎ goal 2/20 · … ◎ goal met after 3 runs: 214 tests pass and lint reports no errors.
A safety-net for destructive commands
Everything runs without asking, except what is destructive: recursive deletes, rewriting git history, DROP. Those wait for your answer, and in print mode they are blocked.
safety-net · rm -rf {"command":"rm -rf build"} → Allow once Allow it for the rest of the session Deny enter select · esc deny
And the rest
- /btw A side question mid-work, answered from the context without tools, without stopping the run or touching the history.
- Prompt suggestions After each run your likely next message shows up dimmed; Tab accepts it.
- Skills Folders with a
SKILL.md, in the Claude Code and Pi format, read from where they already live. - MCP and Code Mode The MCP config from the project, Pi and Claude Code, with OAuth. Tools sit behind a search, and one script can call several at once.
- /context What fills the context window, part by part, on a colour map. Auto-compaction runs before it fills up.
- Models A Claude subscription through the Claude Code login, or any provider Pi supports. Ctrl+P switches.
- Orca In an Orca terminal, tide shows up in the sidebar with the run's state and a spinner on its tab.
Principles
- One user. No profiles, no speculative options. A feature earns its place by being used.
- Light. The core is Pi Durable and pi-tui. Every feature is an extension, with a test.
- Native. No third-party plugins at runtime. A plugin worth having is rewritten as tide code.
- Pinned versions. Durable is experimental, so every dependency has an exact version.
- One source of truth. Skills, subagents,
AGENTS.mdand.mcp.jsonare read from where they already live.
More of what I make at pedrorobalo.com