A tool-use memory layer for AI agents
Agents forget how tools work. Portwright keeps the notebook.
Portwright makes your agent read a short note about a tool before it touches that tool: the procedure that works today, what failed last time and which steps need a human. Markdown files and the Python standard library, nothing else. One git clone.
PW="$HOME/tools/portwright"
git clone https://github.com/foxion37/portwright.git "$PW"
"$PW/bin/portwright" client install codex
"$PW/bin/portwright" check
"$PW/bin/portwright" preflight github Needs git, bash and Python 3.9 or later. Change codex to your client, such as claude-code or cursor.
- Version
- v4.0.2
- License
- MIT, free
- Runs on
- macOS and Linux
- Needs
- git, bash, Python 3.9+
Smart agents still repeat old mistakes.
Hand an agent a GitHub deploy or an API connection and it acts like it is day one. It asks you to paste a token when a connector could do the work, walks you through a dashboard path that has moved and hits the permission error you already fixed. Without memory, it fails the same way twice.
preflight
One call before it touches the tool.
Your agent runs portwright preflight with the tool's name and gets everything at once: a state such as READY or DERIVE REQUIRED, the procedure note, active lessons and a freshness mark. The agent still does the work with its own CLI, MCP or API. Portwright only advises, and it hands steps such as OAuth approval to you.
$ "$PW/bin/portwright" preflight github
READY: github
Profile: (none) no profiles defined
Procedure: services/github.md
Freshness: unknown -> verify-required (no evidence supplied (rule 3))
Tier: confirm
Active Lessons: 3
Three notes
Procedure, Lesson, Profile.
Three kinds of short Markdown notes do the work.
- Procedure: the steps that are correct today, and which of them only a human can do.
- Lesson: what was tried, the confirmed root cause and the corrected move.
- Profile: which GitHub account, secret source and database this project uses.
Fills itself
New tools get a note the first time.
There is no pre-written library of 500 tools. When your agent meets a tool with no note, Portwright reports DERIVE REQUIRED and the agent drafts the current procedure from the official docs. A person reviews the draft before it enters the cache, after checks for secret patterns and unconfirmed causes.
READYA note exists. Read it, then actDERIVE REQUIREDNo note yet. Draft one from official docsfresh | stale | unknownFreshness, never fresh without evidenceauto | confirm | forbidAdvisory tier. Unknown falls back to confirm
Three promises keep it honest.
And a few more things that make it safe to leave running.
Freshness never flatters
fresh needs evidence. Without it the answer is unknown plus "verify first", and unknown is never promoted to fresh.
The tier is advice, not a gate
Portwright reports auto, confirm or forbid and stops there. Your client's own permission prompt enforces it.
The cache fills itself
Knowledge arrives because it was needed, not because someone pre-wrote it.
Profile router
A profile binds each project folder to its GitHub account, env source and databases, so preflight answers for the right account.
Guarded updates
portwright update pulls new notes with git pull --ff-only and re-checks stale ones.
Backups first
Client install writes a .bak backup before it touches your existing settings.
It joins the agent you already use.
Eight clients are supported, including these.
- Claude Code
- Codex
- Gemini CLI
- Cursor
- OpenCode
- Oh My Pi
- VS Code Copilot
Before you start
- Supports macOS and Linux. Windows is not tested. Python below 3.9 is not supported.
- Freshness shows unknown on the first run. That is expected.
- Never write passwords or tokens into notes, only where they are stored. The secret check cannot catch everything.
- Portwright only grades actions. Blocking is left to each client's permission prompt.
- The shared Hub is invite-only and not yet proven on a live server. Treat it as optional.
Clone once. Stop repeating the same failure.
Clone the repository, connect your client and run preflight before the next tool call.