@qinetix/sync-agent
v0.2.0
Published
CLI daemon that syncs local Claude Code memory files to the Qinetix cloud after each session
Readme
@qinetix/sync-agent
CLI daemon that syncs your local Claude Code memory files to the Qinetix cloud after each session, keeping the dashboard and cross-project search up to date.
Installation
npm install -g @qinetix/sync-agentThis makes the qinetix-sync command available globally.
Development (local build)
cd /path/to/qinetix-sync-agent
npm install
npm run build
npm linkQuick Start
Set your API key:
export QINETIX_PM_API_KEY=qpm_your_key_hereGet a key at https://app.qinetix.ai/settings
Initialize in your project:
cd /path/to/your-project qinetix-sync initThis creates
.syncmanifestand registers the project with Qinetix.Start the daemon:
qinetix-sync startThe daemon watches for Claude Code session activity and uploads changed files automatically. Press
Ctrl+Cto stop.
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
| QINETIX_PM_API_KEY | Yes | — | Your qpm_ API key. Never logged or stored to disk. |
| QINETIX_PM_API_BASE | No | https://api.qinetix.ai | Override for staging: https://staging-api.qinetix.ai |
| QINETIX_SYNC_DEBUG | No | — | Set to 1 for verbose debug logging. |
.syncmanifest Format
The .syncmanifest file controls which files are synced:
# Comments start with #
slug: my-project-name # required — cloud identifier
# File patterns (relative to .syncmanifest location):
memory/*.md # glob — syncs all .md files in memory/
session/notes.md # literal pathSee .syncmanifest.example for a full example.
Commands
qinetix-sync --version Print version
qinetix-sync init Create .syncmanifest and register project
qinetix-sync init --slug <s> Override the project slug
qinetix-sync start Start the daemon
qinetix-sync sync Run one sync pass and exit
qinetix-sync sync --force Sync all files, ignoring hash dedup
qinetix-sync status Show server-side sync statusHow It Works
- Session detection: Watches
~/.claude/projects/for file activity (Claude Code writes session data here). - Debounce: Waits 60 seconds after the last activity before triggering a sync pass.
- Hash dedup: Before uploading, fetches server-side hashes via
GET /sync/status. Only changed files are uploaded. - Upload: Sends changed files via
PUT /sync/files. The server computes SHA-256 hashes and queues indexing. - Heartbeat: Falls back to a 30-minute upload if no session activity is observed.
Free-Tier Behavior
If your API key is on the free tier, sync endpoints return an upgrade-required response. The daemon displays:
Sync requires a Pro or Enterprise plan. Visit app.qinetix.ai to upgrade.The daemon keeps running — no crash, no retry loop.
Troubleshooting
QINETIX_PM_API_KEY is not set: Export the environment variable before running qinetix-sync.
Authentication failed: INVALID_API_KEY: Your API key is invalid or expired. Generate a new one at https://app.qinetix.ai/settings.
No .syncmanifest found: Run qinetix-sync init in your project directory first.
No files uploading: Enable debug logging with QINETIX_SYNC_DEBUG=1 qinetix-sync start and check that your .syncmanifest patterns match existing files.
Conflict Resolution
Qinetix Sync uses last-write-wins: when the same file is uploaded by two developers, the most recent upload replaces the prior one. There is no merge, no conflict flag, and no manual resolution step. The synced_at timestamp on each file records which upload won.
This is intentional for v1 — sync is designed for AI context files (MEMORY.md, decisions.md, bugs.md) that are typically owned by one developer at a time. A future sprint may add a conflict-flag UI for teams where simultaneous edits are common.
Development
npm install
npm run build # Compile TypeScript → dist/
npm run typecheck # Type-check without emitting
npm test # Run Vitest test suite
npm run test:watch # Watch mode