All projects

Security Engineering

Prompt Otter: Private Navigation for Long ChatGPT Conversations

A local userscript and Chrome extension

Prompt Otter logo

Personal tool

Released
JavaScriptTampermonkeyChrome ExtensionManifest V3Privacy by DesignDOM EngineeringVirtualized UILocal ProcessingBrowser Tooling

What 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.

  1. 01

    ChatGPT conversation page

  2. 02

    Scoped browser script

  3. 03

    Local prompt discovery

  4. 04

    In-memory prompt index

  5. 05

    Search and jump controls

  6. 06

    Local UI preferences

  7. 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

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

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

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

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.

  1. 01Limited both versions to the ChatGPT domains they need, without broad permissions.
  2. 02Found prompts from page roles and turn details, with fallbacks for less stable page states.
  3. 03Handled virtualized messages with quick and careful loading options.
  4. 04Watched for in-page navigation and rebuilt the prompt list when needed.
  5. 05Kept prompts in memory, saved only interface preferences and checked release versions match.