tx sync
Git-backed JSONL synchronization
Purpose
tx sync manages bidirectional synchronization between the SQLite database and a git-friendly JSONL file. This enables:
- Version control of task history
- Team collaboration via git
- Backup and recovery
- Cross-machine synchronization
Subcommands
| Command | Description |
|---|---|
tx sync export | Export tasks to JSONL file |
tx sync import | Import tasks from JSONL file |
tx sync status | Show sync status |
tx sync auto | Enable/disable automatic sync |
tx sync compact | Compact JSONL by deduplicating operations |
tx sync export
Export all tasks and dependencies to a JSONL file.
Usage
tx sync export [options]Options
| Option | Description |
|---|---|
--path <path> | Output path (default: .tx/tasks.jsonl) |
--json | Output as JSON with operation count |
Examples
# Export to default location
tx sync export
# Export to custom location
tx sync export --path ./backup/tasks.jsonl
# Get operation count
tx sync export --jsonOutput
Exported 42 operations to .tx/tasks.jsonlSync operations are available through the Effect-based core API:
import { createTx, SyncService } from '@jamesaphoenix/tx'
import { Effect } from 'effect'
const tx = createTx()
// Export
await tx.run(
Effect.gen(function* () {
const sync = yield* SyncService
const result = yield* sync.exportToJsonl()
return result
})
)
await tx.close()For most use cases, the CLI commands are recommended for sync operations.
Tool name: tx_sync_export
Arguments:
| Arg | Type | Required | Description |
|---|---|---|---|
path | string | No | Path to JSONL file (default: .tx/tasks.jsonl) |
Example request:
{
"name": "tx_sync_export",
"arguments": {}
}POST /api/sync/exportBody:
{
"path": ".tx/tasks.jsonl"
}Example:
curl -X POST http://localhost:3456/api/sync/export \
-H "Content-Type: application/json" \
-d '{}'tx sync import
Import tasks from a JSONL file using timestamp-based merge.
Usage
tx sync import [options]Options
| Option | Description |
|---|---|
--path <path> | Input path (default: .tx/tasks.jsonl) |
--json | Output as JSON |
Examples
# Import from default location
tx sync import
# Import from custom location
tx sync import --path ./backup/tasks.jsonlMerge Strategy
Import uses timestamp-based merge:
- Newer operations win over older ones
- Conflicts are resolved by comparing
updatedAttimestamps - Operations are applied in chronological order
Sync operations are available through the Effect-based core API:
import { createTx, SyncService } from '@jamesaphoenix/tx'
import { Effect } from 'effect'
const tx = createTx()
// Import
await tx.run(
Effect.gen(function* () {
const sync = yield* SyncService
const result = yield* sync.importFromJsonl()
return result
})
)
await tx.close()For most use cases, the CLI commands are recommended for sync operations.
Tool name: tx_sync_import
Arguments:
| Arg | Type | Required | Description |
|---|---|---|---|
path | string | No | Path to JSONL file (default: .tx/tasks.jsonl) |
Example request:
{
"name": "tx_sync_import",
"arguments": {}
}POST /api/sync/importBody:
{
"path": ".tx/tasks.jsonl"
}Example:
curl -X POST http://localhost:3456/api/sync/import \
-H "Content-Type: application/json" \
-d '{}'tx sync status
Show sync status and whether the database has unexported changes.
Usage
tx sync status [options]Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
tx sync statusOutput
Sync status:
Database tasks: 156
JSONL operations: 312
Last export: 2025-01-28T10:30:00Z
Pending changes: 8Sync operations are available through the Effect-based core API:
import { createTx, SyncService } from '@jamesaphoenix/tx'
import { Effect } from 'effect'
const tx = createTx()
// Get sync status
await tx.run(
Effect.gen(function* () {
const sync = yield* SyncService
const status = yield* sync.status()
return status
})
)
await tx.close()For most use cases, the CLI commands are recommended for sync operations.
Tool name: tx_sync_status
Arguments: None
Example request:
{
"name": "tx_sync_status",
"arguments": {}
}GET /api/sync/statusExample:
curl http://localhost:3456/api/sync/statusResponse:
{
"dbTaskCount": 156,
"jsonlOpCount": 312,
"lastExport": "2025-01-28T10:30:00.000Z",
"lastImport": null,
"isDirty": true,
"autoSyncEnabled": false
}tx sync auto
Enable or disable automatic synchronization on mutations.
Usage
tx sync auto --enable|--disable [options]Options
| Option | Description |
|---|---|
--enable | Enable auto-sync |
--disable | Disable auto-sync |
--json | Output as JSON |
Examples
# Enable auto-sync
tx sync auto --enable
# Disable auto-sync
tx sync auto --disableWhen auto-sync is enabled, every task mutation automatically exports to JSONL.
Sync operations are available through the Effect-based core API:
import { createTx, AutoSyncService } from '@jamesaphoenix/tx'
import { Effect } from 'effect'
const tx = createTx()
// Enable auto-sync
await tx.run(
Effect.gen(function* () {
const autoSync = yield* AutoSyncService
yield* autoSync.enable()
})
)
await tx.close()For most use cases, the CLI commands are recommended for sync operations.
Auto-sync is typically configured through the CLI. Use tx sync auto --enable or tx sync auto --disable to toggle.
The current auto-sync state is included in the tx_sync_status tool response under the autoSyncEnabled field.
Auto-sync is typically configured through the CLI. The current auto-sync state is included in the sync status response:
curl http://localhost:3456/api/sync/status
# Response includes "autoSyncEnabled": true/falsetx sync compact
Compact the JSONL file by deduplicating operations.
Usage
tx sync compact [options]Options
| Option | Description |
|---|---|
--json | Output as JSON |
Examples
tx sync compactOutput
Compacted .tx/tasks.jsonl:
Before: 1,234 operations (256 KB)
After: 892 operations (189 KB)
Saved: 27%Sync operations are available through the Effect-based core API:
import { createTx, SyncService } from '@jamesaphoenix/tx'
import { Effect } from 'effect'
const tx = createTx()
// Compact
await tx.run(
Effect.gen(function* () {
const sync = yield* SyncService
const result = yield* sync.compact()
return result
})
)
await tx.close()For most use cases, the CLI commands are recommended for sync operations.
Tool name: tx_sync_compact
Arguments:
| Arg | Type | Required | Description |
|---|---|---|---|
path | string | No | Path to JSONL file (default: .tx/tasks.jsonl) |
Example request:
{
"name": "tx_sync_compact",
"arguments": {}
}POST /api/sync/compactBody:
{
"path": ".tx/tasks.jsonl"
}Example:
curl -X POST http://localhost:3456/api/sync/compact \
-H "Content-Type: application/json" \
-d '{}'Response:
{
"before": 1234,
"after": 892
}JSONL Format
The export format is newline-delimited JSON:
{"op":"create","id":"tx-abc123","title":"Implement auth","status":"backlog","score":800,"ts":"2025-01-28T10:00:00Z"}
{"op":"update","id":"tx-abc123","status":"active","ts":"2025-01-28T10:30:00Z"}
{"op":"block","taskId":"tx-def456","blockerId":"tx-abc123","ts":"2025-01-28T11:00:00Z"}
{"op":"done","id":"tx-abc123","ts":"2025-01-28T14:00:00Z"}Operation Types
| Operation | Description |
|---|---|
create | New task created |
update | Task fields updated |
delete | Task deleted |
block | Dependency added |
unblock | Dependency removed |
done | Task completed |
Git Workflow
# After completing work
tx sync export
git add .tx/tasks.jsonl
git commit -m "Update tasks"
git push
# On another machine
git pull
tx sync import.gitignore Recommendation
# Track the JSONL, ignore the SQLite database
.tx/tasks.db
.tx/tasks.db-wal
.tx/tasks.db-shm
!.tx/tasks.jsonlTeam Collaboration
Multiple agents or developers can work on the same task database:
- Export before pushing:
tx sync export && git add .tx/tasks.jsonl - Import after pulling:
git pull && tx sync import - Enable auto-sync for real-time updates:
tx sync auto --enable
Merge conflicts in the JSONL file can be resolved by keeping both sides (JSONL is append-friendly) and running tx sync compact afterward.