Local-first AI conversation/persona portability tool with safety-first browser automation.
Project description
PersonaPort
PersonaPort is a local-first Python CLI for moving conversation context and persona data between AI platforms.
WARNING (READ BEFORE USING)
THIS TOOL USES BROWSER AUTOMATION WHICH MAY VIOLATE PLATFORM TOS. USE AT YOUR OWN RISK. RISK OF ACCOUNT BAN. WE STRONGLY RECOMMEND USING OFFICIAL MANUAL EXPORT INSTEAD.
- No passwords are stored in code or logs.
- Sessions are saved as Playwright storage state after manual login.
- Data stays on your machine (
~/.personaportby default). - Use
--safe-mode/--no-scrapefor official export-only workflows.
What It Does
- Opens source platform in a visible browser and reuses saved session.
- Triggers official export flow (safe mode) or fallback scraping (unsafe mode).
- Normalizes history into a neutral schema.
- Extracts persona and compresses history into a compact migration map (topics, tasks, goals, priority threads).
- Uses LiteLLM provider routing with local-first fallback (
ollamafirst, then hosted providers if configured). - Opens target platform and injects migration prompt + optional knowledge files only after interactive confirmation.
Supported Platforms
- Source:
chatgpt,claude,gemini - Target:
chatgpt,claude,gemini
gemini is intentionally conservative in v0.1 (manual guidance + basic automation paths).
Install
git clone https://github.com/0x-Professor/PersonaPort.git
cd personaport
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
playwright install chromium
Repository Structure
PersonaPort/
.github/
ISSUE_TEMPLATE/
workflows/
ci.yml
publish.yml
personaport/
browser/
platforms/
templates/
utils/
cli.py
config.py
db.py
models.py
processor.py
transfer.py
tests/
CONTRIBUTING.md
Makefile
pyproject.toml
README.md
Quick Start
# 1) login once per platform (manual login in opened browser)
personaport login --platform chatgpt
personaport login --platform claude
# 2) safe export + process + migrate package output
personaport export --from chatgpt --to claude --all --safe-mode --no-scrape
# 2a) configure provider key once (stored in OS keyring)
personaport provider set-key --provider groq
# 2b) process using a selected provider/model for persona + summarization
personaport process --file ~/Downloads/chatgpt_export.zip --from chatgpt \
--target claude --all --llm-provider groq --model openai/gpt-oss-20b
# 2b) safe export but continue automatically once you download ZIP from email link
personaport export --from chatgpt --to claude --all --safe-mode --no-scrape --wait-for-export 10
# 2c) provide the downloaded export directly (best for ChatGPT email exports)
personaport export --from chatgpt --to claude --all --safe-mode --no-scrape --export-file ~/Downloads/chatgpt_export.zip
# 2d) same flow for Claude export ZIP
personaport export --from claude --to chatgpt --all --safe-mode --no-scrape --export-file ~/Downloads/claude_export.zip
# 3) process manual export file directly
personaport process --file ~/Downloads/chatgpt_export.zip --from chatgpt
# 3b) process the whole export into one merged migration bundle
personaport process --file ~/Downloads/chatgpt_export.zip --from chatgpt --target claude --all
# 4) migrate a cached session or export file to target platform
personaport migrate --input session --target claude
# 4b) migrate whole cached history (all conversations) to target platform
personaport migrate --input session --source chatgpt --target claude --all
CLI Commands
personaport login --platform <chatgpt|claude|gemini>personaport export --from <platform> --to <platform> --all [--safe-mode] [--no-scrape] [--export-file path] [--wait-for-export N]personaport process --file <export.zip|json> [--from platform] [--all] [--persona "..."] [--llm-provider ...] [--model ...]personaport migrate --input <session|conversation_id|file> --target <platform> [--all] [--llm-provider ...] [--model ...]personaport provider listpersonaport provider set-key --provider <name>personaport provider delete-key --provider <name>
Run personaport --help for global options.
When --export-file is provided, PersonaPort parses the file directly and does not require a source-platform browser session.
Safe Mode
--safe-mode: Only official export actions, no scraping fallback.--no-scrape: Disable scraping even in unsafe mode.--unsafe-mode: Enables fallback scraping and risky flows, requires confirmation.
Local Data Layout
~/.personaport/
config.yaml
personaport.db
sessions/
chatgpt_state.json
claude_state.json
gemini_state.json
exports/
processed/
Supported Export Shapes
- ChatGPT ZIP with sharded files like
conversations-000.json...conversations-XYZ.json(all shards are aggregated). - ChatGPT
chat.htmlfallback exports. - Claude ZIP with
conversations.json, including attachment-only messages (usesextracted_contentwhen text is empty). - Large knowledge payloads are chunked into multiple files for target upload when needed.
- Migration output is compact by default: no full-history dump in upload text; full normalized data remains in local JSON artifacts.
LLM Providers and Keys
Supported summarization/persona providers:
ollama(local, no key)groqopenrouteropenaianthropicgeminitogether
Per-run key injection:
personaport process --file export.zip --llm-provider groq --api-key "<key>"
Provider + model routing example (explicit provider, model name, and temporary key):
personaport process --file export.zip --from chatgpt --target claude \
--llm-provider groq --model openai/gpt-oss-20b --api-key "<groq-key>"
You can also pass custom providers not pre-listed (for LiteLLM-compatible routes):
personaport process --file export.zip --llm-provider myprovider --model myprovider/my-model
Persist key in OS keyring:
personaport provider set-key --provider groq
personaport process --file export.zip --llm-provider groq --model openai/gpt-oss-20b
Fallback order when model/provider fails:
- user-selected model
- provider default model
- configured default model (
config.yaml) - built-in chain (
ollama/llama3.1:8b,groq/openai/gpt-oss-20b,openrouter/...:free)
Security Notes
- Credentials are never hard-coded.
- Secrets can be stored via OS keyring.
- Session state files may contain auth tokens. Protect your local machine and backups.
- If unsure, revoke sessions from the source platform and regenerate.
How It Works Internally
Typer + Richfor CLI UX, warnings, progress, tables.Playwrightfor visible automation (headless=Falsedefault).sqlite3cache for normalized conversations and processed bundles.LiteLLMfor optional persona extraction + summarization (ollama/...default model).Jinja2templates for target-specific migration prompts.
Tests
pytest
CI and Lint
GitHub Actions runs on every push and pull request to master/main:
ruff check .pytest
Run the same checks locally:
make check
Package Publishing
Publishing is configured in .github/workflows/publish.yml:
- Trigger: GitHub Release published.
- Build:
python -m buildandpython -m twine check dist/*. - Publish:
pypa/gh-action-pypi-publishwith either:PYPI_API_TOKENrepository secret (token mode), or- PyPI Trusted Publishing (OIDC mode, when token secret is not set).
Setup steps:
- Create the
personaportproject on PyPI. - Choose one publishing mode:
- Token mode: add repository secret
PYPI_API_TOKEN(recommended for quick setup). - Trusted mode: configure PyPI Trusted Publisher for:
- Owner:
0x-Professor - Repository:
PersonaPort - Workflow:
.github/workflows/publish.yml - Environment: not required
- Owner:
- Token mode: add repository secret
- Publish a GitHub release tag (for example
v0.1.1).
Trusted publishing troubleshooting:
- If you see
invalid-publisherin publish logs, PyPI trusted publisher claims do not match. - Verify the repository/workflow/ref in PyPI exactly match the GitHub run claims.
- Reference: https://docs.pypi.org/trusted-publishers/troubleshooting/
Development Status
v0.1 focuses on safe-mode flows first, then gated risky automation behind explicit confirmation.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file personaport-0.1.0.tar.gz.
File metadata
- Download URL: personaport-0.1.0.tar.gz
- Upload date:
- Size: 37.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30d05db3f46e62ea5b237a8795356ef61b2e371bed0e4749887a9af0ffdd2f92
|
|
| MD5 |
801644ba3986e454bd051e3d0235c13a
|
|
| BLAKE2b-256 |
9a200fab3e3f625f541c8724636dc796316f5c4710d7b5b6bb48a2dac32ce5a3
|
File details
Details for the file personaport-0.1.0-py3-none-any.whl.
File metadata
- Download URL: personaport-0.1.0-py3-none-any.whl
- Upload date:
- Size: 43.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21cbf55d4e13010c175d2ee47df257795857d1d4e8b7849cdeaee59f71729145
|
|
| MD5 |
5fdd8bb7535d89209fa08cd4218d1e02
|
|
| BLAKE2b-256 |
4c6629c5ebe8fc5b57a8ae983158392138c9930832f09e47bfed7634810570c7
|