Skip to content

feat(export): include projects and skills in the account export - #43

Merged
charandeep-reddy merged 2 commits into
charandeep-reddy:mainfrom
webdevsamran:feat/account-export-projects-skills
Aug 20, 2026
Merged

charandeep-reddy merged 2 commits into
charandeep-reddy:mainfrom
webdevsamran:feat/account-export-projects-skills

Conversation

@webdevsamran

Copy link
Copy Markdown
Contributor

Closes #30

What was missing

/api/account/export already bundles chats (with messages), memories, memory packs and settings. It does not include projects or skills.

That means a full export drops every project's instructions and every skill's body/resources — for a BYOK tool whose premise is "your data, your key, your account", those are most of what is worth backing up.

Change

  • Export whole project and skill rows, scoped by userId like every other query.
    Deliberately not listProjects/listSkills: those shape their results for the sidebar and the picker, and neither carries instructions or body.
  • Payload assembly moves to src/lib/account-export.ts so the shape is testable without a database.

On the format

Kept the existing single JSON file rather than a zip. The issue left this open; JSON needs no new client-side dependency, and memories/projects/settings are structured data that a Markdown bundle would flatten. Per-chat Markdown already exists via chatToMarkdown in the share button.

Import/restore stays out of scope, as the issue says.

Tests

New tests/account-export.test.ts. The failure mode for an export is silent omission — a table gets added and nobody remembers to export it — so it asserts every user-owned collection is present via ACCOUNT_EXPORT_COLLECTIONS rather than spot-checking, plus that project instructions and skill bodies survive, and that no API key ever appears.

Verified the test catches the actual bug: against the pre-fix payload shape it fails with export is missing "projects"; it passes after.

bun run typecheck   # clean
bun run lint        # clean
bun run test        # 39 files, 388 passed | 1 skipped

The API key is untouched — it is localStorage-only and never reaches the server.

The account export already bundled chats, messages, memories, memory packs
and settings, but not projects or skills - so a full export dropped every
project's custom instructions and every skill's body, which is most of what
is worth backing up.

Whole rows rather than listProjects/listSkills: those shape their results for
the sidebar and the picker, and neither carries instructions or body.

The payload assembly moves to lib/account-export.ts so its shape can be
tested without a database. The failure mode for an export is silent omission
- a table gets added and nobody remembers to export it - so the test asserts
every user-owned collection is present rather than spot-checking a few.

Closes charandeep-reddy#30
@vercel

vercel Bot commented Aug 18, 2026

Copy link
Copy Markdown

@webdevsamran is attempting to deploy a commit to the charan Team on Vercel.

A member of the Team first needs to authorize it.

@charandeep-reddy

charandeep-reddy commented Aug 18, 2026 •

Copy link
Copy Markdown
Owner

@webdevsamran

This one's basically there. One thing: the skills query in export/route.ts (db.select().from(skill).where(...).orderBy(asc(skill.name))) is identical to what listSkills(userId) already returns — the comment says it's hand-rolled because the shared queries "shape results for the sidebar," but that's true for listProjects (it drops instructions), not listSkills with default args (it's already a full unshaped row, body included). Can you just call listSkills there instead of duplicating the query? One less thing to keep in sync if that function ever changes.

Small non-blocking note: the export route now does 7 independent queries sequentially — could be a Promise.all if export latency ever becomes noticeable, not urgent for this PR.

@charandeep-reddy charandeep-reddy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging as-is and applying the review comment directly on main (reuse listSkills instead of duplicating the query).

@charandeep-reddy
charandeep-reddy merged commit ab46292 into charandeep-reddy:main Aug 20, 2026
1 of 2 checks passed
charandeep-reddy added a commit that referenced this pull request Aug 20, 2026
…lelize the account export

listSkills(userId) with no options already returns every column
including body — the hand-rolled select in the export route was an
exact duplicate that would drift the next time that function changes.

Also runs the seven independent per-collection queries concurrently
instead of sequentially, per the non-blocking note on #43 — export
latency scales with the slowest one now, not the sum.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Export everything: all chats, memories, and settings in one action

2 participants