Security Engineering
Prompt Otter: Private Navigation for Long ChatGPT Conversations
A local userscript and Chrome extension
Personal tool
ReleasedWhat this showed
Released as Prompt Otter v1.0.0 with source code, a privacy policy and browser extension/userscript install options.
What I learned
The simple version works best: narrow permissions, local processing and no backend make the privacy story easy to understand and check.
Release notes
A few notes on scope, evidence and what is kept private.
- The source is public on GitHub.
- The Chrome extension is published.
- A Greasy Fork version is available too.
- The privacy policy explains the local-only approach, and the release tooling checks version consistency.
The short version
Long chats are awkward to navigate when older messages disappear from the page. Prompt Otter keeps a searchable prompt list in the current browser session, so it can jump back to a prompt without a backend, analytics or stored prompt history.
Setup and scope
Plain JavaScript, available as a userscript and a Manifest V3 Chrome extension. It only runs on supported ChatGPT domains and does not use a backend, account system or external API.
What I set out to do
Make long ChatGPT conversations easier to navigate without adding another place where prompt text can end up.
How it handles data
Prompt text stays in the browser session. Only small interface preferences are saved.
01
ChatGPT conversation page
02
Scoped browser script
03
Local prompt discovery
04
In-memory prompt index
05
Search and jump controls
06
Local UI preferences
07
Signed distribution channels
Data paths that stay blocked
Prompt text -> external network
Prompt text -> persistent browser storage
Prompt text -> analytics or tracking service
Prompt text -> extension backend
What stood out
Narrow Execution Scope
Control
What I saw
The userscript metadata and Chrome extension manifest both limit execution to chatgpt.com, www.chatgpt.com and chat.openai.com.
Why it matters
The tool cannot run across unrelated browsing contexts, reducing the amount of page content exposed to the script.
Why it happened
Browser tools embedded into sensitive web applications need explicit execution boundaries.
What would help
Keep host matches narrow, review any future domain additions and avoid broad extension permissions.
Prompt Content Kept Session-Local
Control
What I saw
Prompt records live in the page state. localStorage is used for interface preferences such as panel position, panel size, expanded/collapsed state, hidden state and search text.
Why it matters
Private prompt text is not intentionally written to disk by the tool and is rebuilt as ChatGPT mounts conversation content.
Why it happened
Navigation tools need state, but prompt text is a sensitive asset and should not be persisted by default.
What would help
Add automated tests that assert prompt text is never written to localStorage, sessionStorage or IndexedDB.
No Remote Service Dependency
Control
What I saw
The README, privacy policy and implementation describe no backend, analytics, tracking, accounts, API keys, remote code or prompt submission path.
Why it matters
The core feature works without transferring prompt content to a third party.
Why it happened
A convenience tool embedded in private conversation content should avoid unnecessary network dependencies.
What would help
Add a privacy regression test that monitors network requests during discovery, search and navigation.
Release Integrity Partially Automated
Medium
What I saw
The release tooling validates matching versions across package.json, manifest.json, content.js and prompt-otter.user.js, then builds Chrome, Firefox, userscript and source artifacts.
Why it matters
Repeatable packaging lowers release drift risk, but privacy-specific regression tests and integrity hashes would further strengthen trust.
Why it happened
Distributed userscripts rely on user trust in the published source and update channel.
What would help
Publish release hashes, automate static checks and document a repeatable build/release verification process.
How I worked through it
The main steps, from a first look to a verified result.
- 01Limited both versions to the ChatGPT domains they need, without broad permissions.
- 02Found prompts from page roles and turn details, with fallbacks for less stable page states.
- 03Handled virtualized messages with quick and careful loading options.
- 04Watched for in-page navigation and rebuilt the prompt list when needed.
- 05Kept prompts in memory, saved only interface preferences and checked release versions match.