Project Info
Inspiration
I spend a lot of time working through ideas in ChatGPT. A conversation may start with one simple question, but after a while it includes different options, changing constraints, rejected suggestions, and eventually a decision. The full transcript is still there, but it becomes difficult to see how the thinking actually changed. Search can find a phrase, and a summary can shorten the conversation, but neither really shows the path from the original question to the final direction. That is why I built Trajectory. I wanted a way to look back at a long conversation and quickly understand what happened, what changed, and what mattered.
What it does
Trajectory is a Chrome side-panel extension that analyzes the ChatGPT conversation currently open in the browser. It organizes the conversation into two views: Arc shows the conversation as a sequence of phases. Findings surfaces patterns, tensions, and decisions that appeared across multiple exchanges. Each finding is connected to the phases and messages that support it. With Show in chat, I can jump from a finding directly to the exact words behind it. The goal is not to ask people to blindly trust an AI-generated summary. Trajectory lets them inspect the evidence for themselves.
How we built it
Trajectory is built as a Manifest V3 Chrome extension using a side panel, background worker, and content script. The content script reads the active ChatGPT conversation from the authenticated browser tab. It traverses the thread, extracts the messages, normalizes them, and creates a fingerprint for the current version of the conversation. The extension checks chrome.storage.local for an existing compatible analysis. When it needs a new one, it sends the normalized transcript to a Node.js and Express backend. The backend uses the OpenAI Responses API with Structured Outputs. GPT-5.6 generates the phases, findings, and source references. Before the result appears in the extension, additional validation checks the schema, speaker roles, message references, finding relationships, and exact source excerpts. The backend never tries to fetch a private ChatGPT URL. It also never receives the user’s ChatGPT cookies or account credentials. Analysis only starts when the user requests it, OpenAI requests use store: false, and an updated conversation cannot reuse an outdated result. I used Codex throughout development to inspect the codebase, implement focused changes, reproduce issues, write tests, and run the verification loop. The product decisions came from my own testing and critique, while Codex helped me turn those decisions into working code much faster.
Challenges we ran into
One of the first challenges was extracting the complete conversation. ChatGPT can virtualize parts of the interface, so the messages currently visible on screen may not be the full thread. I needed controlled traversal, completeness checks, stable local message identifiers, and transcript fingerprints. Another challenge was getting the analysis to understand who actually made a decision. ChatGPT may suggest an idea, but that does not mean the user accepted it. Trajectory had to distinguish between a suggestion, rejection, acceptance, implementation, reconsideration, and an unresolved idea. Grounding was another major problem. Some early findings sounded convincing but pointed to the wrong message. I changed the system so an evidence excerpt must be verified against the referenced source before Trajectory can display or open it. The product also became too complicated at several points. Early versions included message scores, charts, fixed perspectives, correction controls, and several overlapping analysis layers. They looked impressive, but they made the conversation harder to understand. I kept removing features until the product had two clear ideas: Arc and Findings. There was also the practical challenge of fitting meaningful analysis into a narrow Chrome side panel without horizontal scrolling, clipped text, or confusing navigation.
Accomplishments we're proud of
I am proud that Trajectory does more than produce another summary. It reconstructs how a conversation developed and surfaces patterns that may be difficult to notice while the discussion is still happening. The part I am most proud of is Show in chat. I can open a finding, inspect one of its supporting exchanges, and jump directly to the exact words behind it without losing my place in Trajectory. I also built deterministic validation around the model output, transcript-aware cache invalidation, responsive side-panel layouts, clear separation between real and prepared data, and a sanitized judge demo that can run without an OpenAI key or private ChatGPT account. The product went through many different versions, but its value can now be explained simply: A long conversation becomes a clear Arc, useful Findings, and evidence you can verify.
What we learned
The biggest lesson was that a better summary was not enough. The more interesting problem was helping people understand how their own thinking developed over time. I also learned that AI-generated analysis becomes much more trustworthy when the user can inspect the exact messages supporting it. Another important lesson was to keep user agency clear. Trajectory should explain the reasoning and decisions already present in a conversation. It should not act as though ChatGPT made those decisions for the user. Finally, I learned that removing features can improve a product more than adding them. The biggest improvements came from deleting scores, fixed lenses, duplicated analysis, and unnecessary navigation.
What's next
The next step is making extraction more resilient when ChatGPT changes its interface, especially for very long conversations and responses that are still streaming. I also want to preserve more of the original content, including formatting, code, and eventually images. Longer term, Trajectory could support projects that span multiple conversations, cloud synchronization, and other AI conversation platforms. Before making the analysis service broadly available, I would also add stronger authentication, quotas, distributed rate limiting, monitoring, and budget controls.
Trajectory
Trajectory is an experimental Manifest V3 Chrome side-panel extension that turns one complete ChatGPT conversation into a concise, source-grounded retrospective.
- Arc reconstructs what happened chronologically.
- Findings identify patterns across multiple exchanges.
- Show in chat verifies a finding against the exact source passage.
Trajectory reads the active authenticated ChatGPT tab through its content script. The backend never fetches private ChatGPT URLs and never receives ChatGPT cookies or account credentials.
Judge quick test — no build required
The repository includes a prepared, sanitized browser sandbox. From the checkout, run:
node scripts/serve-demo.mjs
Open http://127.0.0.1:4173. No dependency install, extension build, ChatGPT account, OpenAI key, or network analysis is required.
Suggested review flow:
- Expand phases in Arc.
- Open Findings and select a finding.
- Expand Supporting phases, Evidence, and Limits.
- Change Compact/Default/Large text size with
Aa. - Resize the browser to inspect the fixed side-panel layout.
The prepared sandbox demonstrates the complete Arc/Findings UI and reviewed
source evidence. Show in chat is simulated because the sandbox is deliberately
not attached to a private ChatGPT conversation. See
docs/judge-guide.md for the test scope and live-plugin
path.
Developer sample
Requirements: Node.js 20.19 or newer and npm.
npm install
npm run sample
Open http://127.0.0.1:5173/responsive-fixture.html. This isolated preview uses reviewed sample messages and analysis. It does not open ChatGPT, call OpenAI, or install the Chrome extension.
The sample supports these query parameters:
?size=compact|default|large
?view=arc|findings
Installation: live extension
-
Install dependencies and create the server environment:
npm install cp .env.example .env -
Set at least these values in the repository-root
.env:OPENAI_API_KEY=your-server-side-key OPENAI_MODEL=a-structured-outputs-compatible-model ALLOWED_ORIGINS=http://localhost:5173 VITE_ANALYSIS_API_URL=http://localhost:8787Never prefix the OpenAI key with
VITE_. Vite variables are bundled into browser code; the API key must remain server-side. -
Start the extension watchers and local analysis server:
npm run dev:live -
Open
chrome://extensions, enable Developer mode, choose Load unpacked, and select this repository'sdist/directory. -
Open a conversation at
https://chatgpt.com, open Trajectory from the extension action, and choose Analyze conversation. -
Reload the unpacked extension from
chrome://extensionsafter a rebuild.
npm run dev is an alias for npm run dev:live.
Supported platforms
| Component | Supported |
|---|---|
| Chrome extension | Desktop Chrome 116+ on macOS, Windows, and Linux |
| Conversation source | Authenticated https://chatgpt.com conversations |
| Analysis server | Node.js 20.19+ on macOS, Windows, or Linux |
| Prepared judge demo | Current Chrome, Edge, Firefox, or Safari with Node.js 20.19+ available to serve static files |
The extension is not currently packaged for Firefox, Safari, mobile Chrome, the ChatGPT desktop app, or other conversation providers.
Environment configuration
The source server, compiled server, smoke test, and live development launcher
all resolve .env from the repository root. To use another file, set
TRAJECTORY_ENV_FILE to its path.
| Variable | Required | Purpose |
|---|---|---|
OPENAI_API_KEY | live | Server-only OpenAI credential |
OPENAI_MODEL | live | Model used by the Responses API |
VITE_ANALYSIS_API_URL | extension | Analysis service URL compiled into the extension |
ALLOWED_ORIGINS | server | Comma-separated browser origins allowed by CORS |
ANALYSIS_PIPELINE_MODE | no | fast (one model call) or thorough (two calls) |
OPENAI_REASONING_EFFORT | no | Model reasoning effort when supported |
OPENAI_TEXT_VERBOSITY | no | low, medium, or high |
PORT | no | Server port; defaults to 8787 |
MAX_TRANSCRIPT_CHARS | no | Maximum normalized transcript size |
MAX_REQUEST_BODY_BYTES | no | Raw JSON request ceiling |
ANALYSIS_TIMEOUT_MS | no | Analysis timeout |
RATE_LIMIT_WINDOW_MS | no | In-memory rate-limit window |
RATE_LIMIT_MAX_REQUESTS | no | Requests allowed per window |
See .env.example for defaults and safety notes.
Useful commands
| Command | What it does |
|---|---|
npm run demo:serve | Serves the committed prepared demo without rebuilding |
npm run sample | Serves the isolated sample UI |
npm run build:sample | Regenerates the committed static demo for maintainers |
npm run dev:live | Builds/watches the extension and starts the live API |
npm run dev:mock | Runs deterministic extension fixture mode after a fixture is prepared |
npm run smoke:openai | Makes a tiny structured OpenAI request using server configuration |
npm run evaluate:analysis | Runs the offline golden quality evaluation |
npm run evaluate:analysis -- --live | Intentionally evaluates the golden transcript with OpenAI |
npm run verify:demo | Validates the bundled demo fixture |
npm test | Runs unit and integration tests without live model calls |
npm run typecheck | Checks extension, scripts, shared code, and server types |
npm run build | Produces extension and server production builds |
npm run check | Runs tests, type checks, and both production builds |
npm start | Starts the already-built analysis server |
Sample data
The repository contains two sanitized datasets:
fixtures/trajectoryGolden.tsis a 50-message regression fixture used by the sample page and analysis-quality checks.src/analysis/fixtures/trajectory-demo.analysis.jsonis a 16-message packaged extension fixture used by explicit mock mode.
The checked-in demo uses a non-routable sample conversation identifier. It is not tied to a private ChatGPT URL. To create a deterministic extension demo for a conversation you control, analyze it in live mode, export the verified fixture, and import it with:
npm run demo:import-fixture -- /path/to/trajectory-demo.fixture.json
npm run verify:demo
npm run dev:mock
Fixture mode is always labeled PREPARED DEMO. Production and live analysis
never silently fall back to sample data.
Architecture
Active ChatGPT tab
-> content-script extraction and controlled full-thread traversal
-> background state scoped to the tab and conversation
-> side-panel fingerprint and local cache lookup
-> user-initiated POST /api/analyze
-> OpenAI Responses API with Structured Outputs
-> deterministic grounding and quality validation
-> Arc and Findings
-> optional exact source-range navigation
The analysis service exposes:
GET /api/health— service and schema health information.POST /api/analyze— complete normalized conversation analysis.
Validated analyses are cached in chrome.storage.local by conversation
identity, transcript fingerprint, analysis schema version, and pipeline
version. A changed transcript cannot reuse a stale analysis as current.
See docs/architecture.md for the extraction, analysis, grounding, caching, and source-navigation design.
How GPT-5.6 and Codex were used
GPT-5.6 and Codex served different roles:
- GPT-5.6 powered the live conversation analysis during submission
development. The server sends the complete normalized transcript through the
Responses API, asks for structured phases, findings, and exact source
references, then applies deterministic validation before rendering anything.
The model remains configurable through
OPENAI_MODEL; it is not bundled into the extension. - Codex accelerated implementation across the Chrome extension, shared schema, Node server, tests, diagnostics, and documentation. It was used to inspect the existing code before edits, implement bounded changes, reproduce errors from console output and screenshots, and run the full verification loop after each change.
The product direction remained human-led. The decisive changes—abandoning message scores, removing fixed lenses and correction controls, reducing the UI to Arc and Findings, and requiring exact source verification—came from explicit product critique and were then implemented and regression-tested with Codex.
See docs/ai-development.md for the decision history, specific acceleration points, and safeguards used to review AI-assisted work.
Repository layout
src/ Chrome side panel, background worker, content script
server/ Express analysis API and OpenAI orchestration
shared/ API types, validation, labels, and quality checks
fixtures/ Golden transcript and reviewed expected analysis
demo/ Prepared static judge sandbox (committed)
scripts/ Development, fixture, smoke, and evaluation tools
docs/ Architecture, development, privacy, and deployment notes
public/manifest.json Chrome extension manifest source
dist/ Generated unpacked extension (ignored)
server-dist/ Generated server build (ignored)
Privacy and operational limits
- Analysis is user initiated outside explicit fixture mode.
- OpenAI requests use
store: false. - The server logs counts, sizes, request IDs, latency, token usage, and status; it does not log conversation text, titles, URLs, model output, or credentials.
- The included rate limiter is process-local demo protection, not production authentication, billing control, or distributed abuse prevention.
- A publicly reachable endpoint can create material OpenAI cost. Add durable authentication, quotas, distributed rate limiting, monitoring, and budget controls before exposing it broadly.
See docs/privacy-and-deployment.md before deploying the server.
Verification and contributions
Before opening a change:
npm run check
Automated tests never call OpenAI. Live smoke and quality evaluation commands must be invoked explicitly.
See docs/judge-guide.md for submission testing, CONTRIBUTING.md for the development workflow, and SECURITY.md for reporting security issues.
Known limitations
- ChatGPT's DOM, virtualization, and route structure are not public stable APIs.
- Rich text and code are normalized to plain text; images are not analyzed.
- Very long or actively streaming threads may not be verifiably complete.
- Exact source grounding prevents mismatched navigation but does not guarantee that every model interpretation is useful.
- There are no accounts, cloud sync, background monitoring, or cross-conversation projects.
Before publishing a fork
This project intentionally ignores .env, generated builds, logs, coverage,
and evaluation artifacts. Before pushing a new repository:
git init
git status --ignored
npm run check
Review the staged diff and sample transcripts manually. Do not force-add
.env, dist/, server-dist/, artifacts/, private ChatGPT URLs, or real
conversation/project identifiers. Commit the generated demo/ directory so
judges can run the prepared sandbox without rebuilding it.
License
Trajectory is available under the MIT License.
Analysis
View
Metric
- 1
Figures cover GitHub contributors during the hackathon window. A co-authored commit counts in full for each author, so per-member totals add up to more than the whole-team figures.
Technology
- CSSIn code
- ExpressIn code
- HTMLIn code
- JavaScriptIn code
- OpenAIIn code
- ReactIn code
- TypeScriptIn code
- Node.jsClaimed
7 of 8 appear in the indexed code. 1 claimed on Devpost could not be matched to code, which may simply mean the tool leaves no trace in the repository.
AI coding agents
No AI coding agent signals were found in this repository.
Detected from committed agent config files and commit authorship. Absence of a signal is not proof an agent was unused.
Codebase size
Source size
914 KB
Source files
98
Counts recognized source files only; vendored directories, binaries and lockfiles are excluded, so this is smaller than the repository on disk.
Repository
michi883/trajectory
113 files · 1.1 MB · @ b98e885
Structure
Interface
10 files · 9%Screens, components and styles rendered to the user.
API & routing
16 files · 14%Request entry points: routes, handlers and controllers.
Application logic
29 files · 26%Domain rules, services and shared utilities.
+1 more
Supporting
Layers are inferred from where files sit in the tree, not from reading the code. A project that names its directories unconventionally will read oddly here — open the file browser to check anything the diagram implies.
Languages
- TypeScript60%
- JavaScript31%
- CSS4%
- Markdown4%
- HTML1%
- YAML0%
Share of indexed source by file size. Binary and vendored files are excluded.
Dependencies
package.json
npm · 18- dotenv
- express
- openai
- react
- react-dom
- zod
- +12 more
Declared in the repository’s manifests at the indexed commit. A declared package is not proof it is used, and runtime dependencies are listed first.
This project’s features have not been analysed yet.
Export this project's context (description, README, evidence, key source files) to chat with an AI agent elsewhere.