data-export-and-restore
Builds data export and restore - a versioned, checksummed backup file, all-or-nothing restore, safe CSV.
Skill by zakariaf
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/zakariaf-data-export-and-restore
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: spreadsheets, backend, data
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 26, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
- Runs as
- Node.js package
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/data-export-and-restore
What's inside
- Skill name
data-export-and-restore- Description
- Builds data export and restore - a versioned, checksummed backup file, all-or-nothing restore, safe CSV. Use when adding backup, restore, import, export or CSV files. Not for the database (persistence-and-migrations).
- License
- MIT
- Instructions
- 212 lines in SKILL.md · view on GitHub
Before installing
- Ships executable scripts
Files (87)
- SKILL.md
- shared.json · assets/
- template-placeholders.json · assets/
- backup-schema.ts · examples/backup-v2/src/data/backup/
- backup-upgrades.ts · examples/backup-v2/src/data/backup/
- backup-v2.json · examples/backup-v2/src/data/backup/fixtures/
- sqlite-backup-repository.ts · examples/backup-v2/src/data/backup/
- v0002-add-task-due-on.ts · examples/backup-v2/src/data/backup/upgrades/
- migrations.ts · examples/backup-v2/src/data/migrations/
- v0002-add-task-due-date.ts · examples/backup-v2/src/data/migrations/
- backup-round-trip.test.ts · examples/backup-v2/test/sqlite/
- architecture.json · examples/contracts/
- backup-failure-messages.ts · examples/src/features/backup/
- backup-screen.tsx · examples/src/features/backup/
- backup-action.tsx · examples/src/features/backup/components/
- restore-confirmation.tsx · examples/src/features/backup/components/
- use-backup-model.ts · examples/src/features/backup/
- csv-and-formats.md · references/
- envelope-and-ladder.md · references/
- platform-behaviour.md · references/
- restore-policy.md · references/
- testing-and-checker.md · references/
- check-backup.mjs · scripts/
- check-lib.mjs · scripts/
- inspect-backup.mjs · scripts/
- backup-envelope.mjs · scripts/lib/
- backup-rules.mjs · scripts/lib/
- repo-rules.mjs · scripts/lib/
- source-scan.mjs · scripts/lib/
- selftest.mjs · scripts/
- canonical-json.test.ts · templates/src/core/portable/
- canonical-json.ts · templates/src/core/portable/
- csv.test.ts · templates/src/core/portable/
- csv.ts · templates/src/core/portable/
- sha256.test.ts · templates/src/core/portable/
- sha256.ts · templates/src/core/portable/
- utf8.ts · templates/src/core/portable/
- result.test.ts · templates/src/core/
- result.ts · templates/src/core/
- backup-envelope.test.ts · templates/src/data/backup/
- backup-envelope.ts · templates/src/data/backup/
- backup-failures.ts · templates/src/data/backup/
- backup-repository.ts · templates/src/data/backup/
- backup-schema.ts · templates/src/data/backup/
- backup-service.test.ts · templates/src/data/backup/
- backup-service.ts · templates/src/data/backup/
- backup-upgrade-step.ts · templates/src/data/backup/
- backup-upgrades.test.ts · templates/src/data/backup/
- backup-upgrades.ts · templates/src/data/backup/
- fake-backup-repository.test.ts · templates/src/data/backup/
- fake-backup-repository.ts · templates/src/data/backup/
- backup-v1.json · templates/src/data/backup/fixtures/
- read-backup.test.ts · templates/src/data/backup/
- read-backup.ts · templates/src/data/backup/
- sqlite-backup-repository.ts · templates/src/data/backup/
- tasks-csv.test.ts · templates/src/data/backup/
- tasks-csv.ts · templates/src/data/backup/
- migration-runner.ts · templates/src/data/migrations/
- sql-driver.ts · templates/src/data/
- expo-file-system-export-files-adapter.ts · templates/src/services/export-files/
- …and 27 more
SKILL.md (first lines)
# Data export and restore
A backup is a versioned, checksummed file of the user's tables that this app (and only a backup) can
restore; a restore checks the whole file first, keeps a safety copy, then replaces every table in one
transaction or changes nothing; a CSV export is guarded against broken rows and formula injection; files
leave or enter the app only through ports, from a press; tests prove the round trip byte for byte.
## Rules that must hold
1. **Backup and export are different features; restore accepts only the backup envelope.** A CSV or a
report is lossy and never restorable (it fails as `not-a-backup`). Why: the moment a CSV restores, a
format built for reading becomes someone's only copy, with no versions, types or checksum.
2. **Every backup is the envelope: `format`, `formatVersion`, `schemaVersion`, `appVersion`,
`exportedAt` (UTC), `payloadSha256`, in that order, then the canonical payload last;
`BACKUP_SCHEMA_VERSION = LATEST_DB_VERSION`.** Why: an unversioned file can only be misread, never
refused, and header first lets a truncated file of ours be called damaged. (`envelope-header`,
`schema-version`)
3. **A picked file climbs the whole ladder before anything is written**: size (the one
`MAX_BACKUP_BYTES`, which export also refuses to exceed), readable, ours, strict
header, checksum before any row, not newer than the build, every row through its schema (text bounds
in code points, as SQLite counts), ids unique and parents present. The name and MIME type are never
trusted. Why: a broken file must fail with its own reason, not half-way through the rows.
(`checksum-first`, `newer-refused`)
4. **Restore is replace, all or nothing**: the user confirms a preview that names the policy and the
counts (and the unreadable current rows the replace also removes); the current data is written to a
private safety copy first (no copy, or one over the size limit, no restore); then one
transaction deletes and inserts every backed-up table, ids kept; a preview restores once; never into
a session running in memory. The app offers the copy back (`previewSafetyCopy`), because no picker
can reach the private folder. Why: a half-restored database is worse than a failed restore, and the
copy is the undo for restoring the wrong file. (`restore-transaction`, `safety-copy-first`)
5. **A backup covers every user table and never a protected one**: each table the migrations create is
in `BACKUP_PAYLOAD` or in `BACKUP_EXCLUDED_TABLES` with its reason; entitlements, diagnostics and
secrets are never backed up or restored. Why: a forgotten table is data lost on the next restore, and
a restorable entitlement is a free purchase for anyone who edits the file. (`backup-coverage`,
`restore-protected`)
6. **Older backups upgrade through frozen, pure JSON steps, one per migration, proven equal to the
migrations by the parity test; every schema version has a frozen backup fixture.** Why: users hold
files from every version, and two upgrade paths drift apart unless a test pins them together.
(`upgrade-chain`, `backup-fixture`)
7. **The round-trip test passes on hostile data**: export, restore into an empty database, export again
gives the same bytes; restoring twice gives the same rows; every refusal leaves the data unchanged.
Why: `'test1'` survives everything and proves nothing. (`round-trip-test`)
8. **Machine formats hold canonical values only**: integers, `.` decimals, ISO-8601 UTC or epoch ms,
date keys, codes, untranslated column names; localization happens on screen. Why: `12,5`, `١٢٫٥` and
`12.5` are one number and three parses. (`canonical-values`)
9. **Every CSV goes through the one guarded encoder**: a text cell starting with `= + - @`, tab or CR
gets an apostrophe, then RFC 4180 quoting (quotes doubled, spaces and newlines kept), CRLF, UTF-8 with
a BOM for spreadsheets. Why: a hand-joined cell breaks on a comma and runs as a formula in the
recipient's spreadsheet. (`csv-guard`, `csv-hand-rolled`)
10. **Files are published atomically**: a temp file in the same folder, moved over the published name,
deleted on failure; free space checked first; shared exports live in the cache and are swept on the
next export, never deleted when the share sheet closes. Why: a truncated file with a trusted name is
the failure that surfaces months later. (`atomic-write`)
11. **The share sheet, the picker and the file system sit behind ports, and run only from a user's
press**; these ports never upload. Why: Jest never touches native code, and a file leaves through
them only when the user asks. An opt-in scheduled cloud backup is a separate feature with the same
envelope and ladder. (`sdk-behind-port`, `user-action-only`)
12. **Export, pick and restore return typed Results with one failure kind per reason; backup code never
throws.** Why: "Restore failed" alone cannot be told apart from data loss. (`typed-failures`)
## Workflow
1. Read [references/envelope-and-ladder.md](references/envelope-and-ladder.md) (the file, the checksum,
the ladder, upgrades, fixtures) and [references/restore-policy.md](references/restore-policy.md)
(replace, the transaction, the safety copy, the confirmation, excluded tables).
2. Prerequisites: the app database from persistence-and-migrations (`SqlDriver`, migrations,
`contracts/persistence.json`, `AppData`) and the Result module from error-handling-typed-results. Then
`npx expo install expo-file-system expo-sharing expo-document-picker` (SDK 57: `~57.0.7`,
`~57.0.22`, `~57.0.3`; verified 2026-10-10; re-verify with `npx expo install --check`).
3. Stop and ask the developer to classify the two new SDKs (an architecture decision): merge
`examples/contracts/architecture.json` into the app's `contracts/architecture.json` and add both to
`VENDOR_SDK_PATHS` in `eslint.config.mjs` in the same commit
([references/platform-behaviour.md](references/platform-behaviour.md), section 7).
4. Copy the templates: `templates/src/core/portable/`, `templates/src/data/backup/` (with
`fixtures/backup-v1.json`), `templates/src/services/{export-files,share-sheet,file-picker}/`,
`templates/test/portable/`, `templates/test/sqlite/{sqlite-backup-repository,backup-round-trip}.test.ts`
(skip the synced files the app already has from their owners). Replace `__APP_SLUG__` (the format
marker and file names). Replace the Tasks tables with the app's own in `backup-schema.ts`, the SQLite
backup repository (literal SELECT/DELETE/INSERT per table, children of a skipped parent left out in
`readAll`), `consistencyFailure`, `tasks-csv.ts`, the frozen fixture and the tests; list every other
table in `BACKUP_EXCLUDED_TABLES` with its reason. Set `FIRST_BACKUP_SCHEMA_VERSION` in
`backup-envelope.ts` to the app's current `LATEST_DB_VERSION` (the template's `1` fits only an app
whose database is still at version 1); it never changes after the first release with backups. No
upgrade steps or fixtures exist for versions before it: never invent them to satisfy the checker.
5. Make the frozen fixture for the current schema (N = `FIRST_BACKUP_SCHEMA_VERSION`): export with the
app over hostile rows (quotes, `=1+2`, CRLF, RTL with marks, emoji at the maximum length, blanks, a
gap in ids) and commit it as `src/data/backup/fixtures/backup-v<N>.json` with its FIXTURES entry,
replacing the template's `backup-v1.json` when N > 1. Never edit it afterwards.
6. Compose once: the three adapters in `createDeviceServices` (fakes in `createTestServices`), and
`backup: createBackupService({ ..., isPersistent: database.isPersistent })` in the data layer's device
opener as a member of `AppData` (platform-behaviour.md, section 7).
7. Build the screen from `examples/src/features/backup/` (model, pure view, one message per failure
kind): one action at a time with the busy state painted first, an iPad anchor per share button, the
confirmation naming "replace", both counts and the date formatted on screen, the "Restore the data
from before your last restore" row, `skippedRows` and `currentSkippedRows` shown, a failed phase
when a job throws (never stuck on working), and the restore run through the store
layer's `updateAndPublish` so every store re-reads. CSV and reports:
[references/csv-and-formats.md](references/csv-and-formats.md).
8. A table changes later: follow "Adding schema version N+1" in envelope-and-ladder.md, imitating
`examples/backup-v2/`, in the same change as the migration.
9. Run the tests ([references/testing-and-checker.md](references/testing-and-checker.md)):
`npx jest src/core/portable src/data/backup src/services/export-files src/services/share-sheet src/services/file-picker test/sqlite --ci`
and `npm run typecheck`.
10. After an adapter change, run the export-share-restore drill on a named iOS simulator and Android
emulator (platform-behaviour.md, section 8), or say in the report that it is owed.
11. Run `node ${CLAUDE_SKILL_DIR}/scripts/check-backup.mjs .`; fix every `FAIL` line and rerun until it
prints `RESULT: PASS`. For a user's file: `node ${CLAUDE_SKILL_DIR}/scripts/inspect-backup.mjs <file> --format <slug>.backup --schema <N>`.
## Definition of done
- [ ] Backup and CSV are separate actions; the envelope's header comes first in the order of rule 2, the
payload is canonical JSON and `payloadSha256` its SHA-256; `BACKUP_SCHEMA_VERSION = LATEST_DB_VERSION`.
- [ ] `readBackup` runs the whole ladder with one failure kind per reason, the checksum before any row,
newer files refused; the picked file's size is checked before it is read, and export refuses a
backup above the same `MAX_BACKUP_BYTES` or one that fails rung 7.
- [ ] Restore shows a preview naming "replace" and the counts, writes the safety copy first, replaces in
one transaction (ids kept), restores a preview once, refuses a session in memory; stores re-read
afterwards; the screen offers the safety copy back through `previewSafetyCopy`.
- [ ] Every migrated table is backed up or excluded with its reason; no protected table, secret orFrom zakariaf/ReactNative-Skills, MIT.
More from zakariaf/ReactNative-Skills
- 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
android-release-play
zakariaf
Ships Android App Bundles to Google Play: upload key, Play App Signing, AAB gate, versionCode, tracks, rollout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
architecture-and-boundaries
zakariaf
Places app code in the src/ layout and checks import boundaries: one-way zones, pure core, ports with fakes, one composition root.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
async-safety
zakariaf
Prevents silent async bugs: effect races, stale results, lost promises, leaked listeners and timers, AbortSignal gaps.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
audio-and-haptics-feedback
zakariaf
Builds SFX and haptics behind ports.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
auth-and-secure-storage
zakariaf
Builds sign-in - tokens in expo-secure-store, shared refresh, protected routes, OAuth PKCE, Apple sign-in.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
background-tasks
zakariaf
Builds expo-background-task jobs: idempotent, budgeted runs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9
Signals
- Stars
- 11
- Forks
- 2
- Open issues
- 0
- Last commit (this folder)
- Oct 17, 2026 (11 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/zakariaf/ReactNative-Skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from zakariaf
- 0.606score
admob-ads-and-consent
zakariaf
Builds AdMob ads behind a port - banners, interstitials, rewarded, UMP consent then ATT, pacing, ADS_MODE test IDs.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
accessibility-as-code
zakariaf
Enforces a11y labels, 44pt targets, 200% text, VoiceOver, TalkBack.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
canvas-gestures-and-hit-testing
zakariaf
Turns canvas taps, swipes, drags and aim into typed intents: one gesture module, hit-testing on the drawn layout.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
adaptive-layout
zakariaf
Lays screens out by window, not device: breakpoints, master-detail panes, readable widths, grids.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
debug-menu-and-test-hooks
zakariaf
Gates test-only code behind one literal TEST_ONLY switch: debug menu, debug link, simulated clock and offline.
SkillAFreshness: A★ 11Claude Code +9 - 0.606score
analytics-and-consent
zakariaf
Gates analytics on opt-in consent: no SDK before a yes, typed events without personal data, ATT.
SkillAFreshness: A★ 11Claude Code +9
Cite this page
data-export-and-restore skill. Agent Mart. https://agentmart.dev/skills/zakariaf-data-export-and-restore (last updated 2026-10-24)