freestyle-sync 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,46 +1,12 @@
1
1
  # Freestyle Sync
2
2
 
3
- Sync your current directory, it's dependencies, and your agent context into a remote runtime. Freestyle VMs support snapshots so only changes are uploaded on later runs.
3
+ Offload any development environment to a VM with 1 command. Authentication, agent context, and dependencies are automatically handled.
4
4
 
5
5
  ```
6
6
  npx freestyle-sync
7
7
  ```
8
8
 
9
- Freestyle VMs are the default provider. You can sync into a local Apple container on macOS with the Apple `container` CLI installed:
10
-
11
- ```sh
12
- npx freestyle-sync --provider apple-container --apple-container-image ubuntu:24.04
13
- ```
14
-
15
- Use `--vm-id <container-name-or-id>` to reuse an existing Apple container. Snapshot caching is only available with the Freestyle provider.
16
-
17
- Use the SDK when embedding sync inside another CLI/app (no required `freestyle-sync.config.ts` or cache file):
18
-
19
- ```ts
20
- import { defineConfig, sync, type SyncCache } from "freestyle-sync";
21
- import { gitAuthPlugin } from "@freestyle-sync/auth-git";
22
- import { nodeNpmPlugin } from "@freestyle-sync/node-npm";
23
-
24
- let cache: SyncCache | undefined;
25
-
26
- const result = await sync({
27
- config: defineConfig({
28
- plugins: [gitAuthPlugin(), nodeNpmPlugin()],
29
- }),
30
- options: {
31
- projectRoot: process.cwd(),
32
- autoSsh: false,
33
- },
34
- cache,
35
- onCacheUpdate(nextCache) {
36
- cache = nextCache;
37
- },
38
- });
39
-
40
- console.log("synced runtime", result.vmId);
41
- ```
42
-
43
- freestyle-sync creates `freestyle-sync.config.mjs` on first run and installs the config dependencies into your project as dev dependencies. Remove the generated config or dependencies if you want to reset it later.
9
+ On it's first run, freestyle-sync creates `freestyle-sync.config.mjs` and configures a large set of default plugins. Plugins help sync parts of your development environment that require more complex logic than just copying the current directory's files.
44
10
 
45
11
  ```js
46
12
  import { defineConfig } from "freestyle-sync";
@@ -57,8 +23,11 @@ import { githubCliAuthPlugin } from "@freestyle-sync/auth-github-cli";
57
23
  import { npmAuthPlugin } from "@freestyle-sync/auth-npm";
58
24
  import { sshAuthPlugin } from "@freestyle-sync/auth-ssh";
59
25
  import { yarnAuthPlugin } from "@freestyle-sync/auth-yarn";
26
+ import { nextjsPlugin } from "@freestyle-sync/nextjs";
60
27
  import { nodeNpmPlugin } from "@freestyle-sync/node-npm";
28
+ import { rustPlugin } from "@freestyle-sync/rust";
61
29
  import { shellHistoryPlugin } from "@freestyle-sync/shell-history";
30
+ import { vitePlugin } from "@freestyle-sync/vite";
62
31
 
63
32
  export default defineConfig({
64
33
  plugins: [
@@ -73,6 +42,9 @@ export default defineConfig({
73
42
  azureAuthPlugin(),
74
43
  gcloudAuthPlugin(),
75
44
  nodeNpmPlugin(),
45
+ nextjsPlugin(),
46
+ vitePlugin(),
47
+ rustPlugin(),
76
48
  claudeAgentPlugin(),
77
49
  codexAgentPlugin(),
78
50
  copilotAgentPlugin(),
@@ -81,7 +53,7 @@ export default defineConfig({
81
53
  });
82
54
  ```
83
55
 
84
- Project sync can exclude folders and include additional local paths. Include paths may point outside the project directory; they are copied into the remote project at the configured relative target.
56
+ You can exclude folders and include additional local paths. Include paths may point outside the project directory; they are copied into the remote project at the configured relative target.
85
57
 
86
58
  ```js
87
59
  export default defineConfig({
@@ -90,15 +62,50 @@ export default defineConfig({
90
62
  include: [
91
63
  { source: "../shared-config", target: "shared-config" },
92
64
  ],
93
- },
94
- plugins: [
95
- nodeNpmPlugin(),
96
- ],
65
+ }
97
66
  });
98
67
  ```
99
68
 
100
- `nodeNpmPlugin()` excludes `node_modules` from upload by default and installs dependencies on the remote runtime using the project lockfile: `pnpm install --frozen-lockfile`, Yarn `--frozen-lockfile`/`--immutable`, or `npm ci`. To keep the previous behavior of syncing `node_modules` and only repairing native/workspace packages remotely, use:
69
+ The default Node/framework/runtime plugins avoid uploading generated dependency and build output folders:
70
+
71
+ ```js
72
+ nodeNpmPlugin() // excludes node_modules and installs frozen dependencies remotely
73
+ nextjsPlugin() // excludes .next
74
+ vitePlugin() // excludes dist, build, and .vite
75
+ rustPlugin() // excludes target, installs Rust/Cargo, and runs cargo fetch
76
+ ```
77
+
78
+ You can keep uploading those generated folders when needed:
101
79
 
102
80
  ```js
103
81
  nodeNpmPlugin({ syncNodeModules: true })
82
+ nextjsPlugin({ syncNextDir: true })
83
+ vitePlugin({ syncBuildOutput: true })
84
+ rustPlugin({ syncTargetDir: true })
85
+ ```
86
+
87
+ If you're integrating freestyle-sync into your own toolchain, you can use it as an sdk and take full control over how configuration and cache is stored.
88
+
89
+ ```ts
90
+ import { defineConfig, sync, type SyncCache } from "freestyle-sync";
91
+ import { gitAuthPlugin } from "@freestyle-sync/auth-git";
92
+ import { nodeNpmPlugin } from "@freestyle-sync/node-npm";
93
+
94
+ let cache: SyncCache | undefined;
95
+
96
+ const result = await sync({
97
+ config: defineConfig({
98
+ plugins: [gitAuthPlugin(), nodeNpmPlugin()],
99
+ }),
100
+ options: {
101
+ projectRoot: process.cwd(),
102
+ autoSsh: false,
103
+ },
104
+ cache,
105
+ onCacheUpdate(nextCache) {
106
+ cache = nextCache;
107
+ },
108
+ });
109
+
110
+ console.log("synced runtime", result.vmId);
104
111
  ```
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ import type { CliOptions, PushvmConfig, VmProviderName } from "./plugin-api.ts";
4
+ export * from "./plugin-api.ts";
5
+ type FileKind = "file" | "symlink";
6
+ type FileDigest = {
7
+ hash: string;
8
+ kind: FileKind;
9
+ mode: number;
10
+ size: number;
11
+ };
12
+ type CacheFile = {
13
+ version: number;
14
+ projectRoot: string;
15
+ remoteProjectDir: string;
16
+ provider?: VmProviderName;
17
+ vmId?: string;
18
+ snapshotId?: string;
19
+ projectFiles: Record<string, FileDigest>;
20
+ contextFiles: Record<string, FileDigest>;
21
+ snapshotProjectFiles?: Record<string, FileDigest>;
22
+ snapshotContextFiles?: Record<string, FileDigest>;
23
+ envHash?: string;
24
+ snapshotEnvHash?: string;
25
+ updatedAt?: string;
26
+ };
27
+ type PluginPreferences = {
28
+ version: number;
29
+ disabledPlugins: string[];
30
+ updatedAt?: string;
31
+ };
32
+ export type SyncCache = CacheFile;
33
+ export type SyncPluginPreferences = PluginPreferences;
34
+ export type SyncSdkOptions = {
35
+ config: PushvmConfig;
36
+ options?: Partial<CliOptions>;
37
+ cache?: SyncCache;
38
+ pluginPreferences?: SyncPluginPreferences;
39
+ onCacheUpdate?(cache: SyncCache): Promise<void> | void;
40
+ };
41
+ export type SyncSdkResult = {
42
+ vmId?: string;
43
+ cache: SyncCache;
44
+ snapshotId?: string;
45
+ };
46
+ export declare function sync(sdkOptions: SyncSdkOptions): Promise<SyncSdkResult>;
package/dist/src/main.js CHANGED
@@ -47,8 +47,11 @@ const DEFAULT_CONFIG_DEPENDENCIES = [
47
47
  { name: "@freestyle-sync/auth-npm", spec: "@freestyle-sync/auth-npm@latest" },
48
48
  { name: "@freestyle-sync/auth-ssh", spec: "@freestyle-sync/auth-ssh@latest" },
49
49
  { name: "@freestyle-sync/auth-yarn", spec: "@freestyle-sync/auth-yarn@latest" },
50
+ { name: "@freestyle-sync/nextjs", spec: "@freestyle-sync/nextjs@latest" },
50
51
  { name: "@freestyle-sync/node-npm", spec: "@freestyle-sync/node-npm@latest" },
52
+ { name: "@freestyle-sync/rust", spec: "@freestyle-sync/rust@latest" },
51
53
  { name: "@freestyle-sync/shell-history", spec: "@freestyle-sync/shell-history@latest" },
54
+ { name: "@freestyle-sync/vite", spec: "@freestyle-sync/vite@latest" },
52
55
  ];
53
56
  const pluginUtils = {
54
57
  checkedExec,
@@ -375,8 +378,11 @@ import { githubCliAuthPlugin } from "@freestyle-sync/auth-github-cli";
375
378
  import { npmAuthPlugin } from "@freestyle-sync/auth-npm";
376
379
  import { sshAuthPlugin } from "@freestyle-sync/auth-ssh";
377
380
  import { yarnAuthPlugin } from "@freestyle-sync/auth-yarn";
381
+ import { nextjsPlugin } from "@freestyle-sync/nextjs";
378
382
  import { nodeNpmPlugin } from "@freestyle-sync/node-npm";
383
+ import { rustPlugin } from "@freestyle-sync/rust";
379
384
  import { shellHistoryPlugin } from "@freestyle-sync/shell-history";
385
+ import { vitePlugin } from "@freestyle-sync/vite";
380
386
  import { defineConfig } from "freestyle-sync";
381
387
 
382
388
  export default defineConfig({
@@ -392,6 +398,9 @@ export default defineConfig({
392
398
  azureAuthPlugin(),
393
399
  gcloudAuthPlugin(),
394
400
  nodeNpmPlugin(),
401
+ nextjsPlugin(),
402
+ vitePlugin(),
403
+ rustPlugin(),
395
404
  claudeAgentPlugin(),
396
405
  codexAgentPlugin(),
397
406
  copilotAgentPlugin(),
@@ -414,8 +423,11 @@ import { githubCliAuthPlugin } from "@freestyle-sync/auth-github-cli";
414
423
  import { npmAuthPlugin } from "@freestyle-sync/auth-npm";
415
424
  import { sshAuthPlugin } from "@freestyle-sync/auth-ssh";
416
425
  import { yarnAuthPlugin } from "@freestyle-sync/auth-yarn";
426
+ import { nextjsPlugin } from "@freestyle-sync/nextjs";
417
427
  import { nodeNpmPlugin } from "@freestyle-sync/node-npm";
428
+ import { rustPlugin } from "@freestyle-sync/rust";
418
429
  import { shellHistoryPlugin } from "@freestyle-sync/shell-history";
430
+ import { vitePlugin } from "@freestyle-sync/vite";
419
431
  import { defineConfig } from "freestyle-sync";
420
432
 
421
433
  export default defineConfig({
@@ -431,6 +443,9 @@ export default defineConfig({
431
443
  azureAuthPlugin(),
432
444
  gcloudAuthPlugin(),
433
445
  nodeNpmPlugin(),
446
+ nextjsPlugin(),
447
+ vitePlugin(),
448
+ rustPlugin(),
434
449
  claudeAgentPlugin(),
435
450
  codexAgentPlugin(),
436
451
  copilotAgentPlugin(),
@@ -1581,6 +1596,8 @@ async function runInstall(vm, projectRoot, remoteProjectDir) {
1581
1596
  await checkedExec(vm, `cd ${shellQuote(remoteProjectDir)} && ${installCommand}`, 20 * 60 * 1000);
1582
1597
  }
1583
1598
  async function detectInstallCommand(projectRoot) {
1599
+ if (await exists(path.join(projectRoot, "bun.lock")) || await exists(path.join(projectRoot, "bun.lockb")))
1600
+ return "bun install --frozen-lockfile";
1584
1601
  if (await exists(path.join(projectRoot, "pnpm-lock.yaml")))
1585
1602
  return "corepack enable && pnpm install --frozen-lockfile";
1586
1603
  if (await exists(path.join(projectRoot, "yarn.lock")))
@@ -1648,11 +1665,13 @@ async function uploadArchiveInChunks(vm, vmId, archivePath, remoteArchivePath, l
1648
1665
  const width = String(chunkCount - 1).length;
1649
1666
  const canRenderInlineProgress = process.stdout.isTTY;
1650
1667
  const logEvery = Math.max(1, Math.ceil(chunkCount / 4));
1668
+ const chunkManifest = [];
1651
1669
  let index = 0;
1652
1670
  for await (const chunk of createReadStream(archivePath, { highWaterMark: ARCHIVE_CHUNK_BYTES })) {
1653
- const chunkName = `${String(index).padStart(width, "0")}.chunk.b64`;
1671
+ const chunkName = `${String(index).padStart(width, "0")}.chunk`;
1654
1672
  const content = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
1655
- await vm.fs.writeTextFile(`${chunkDir}/${chunkName}`, content.toString("base64"));
1673
+ chunkManifest.push(`${chunkName} ${content.length}`);
1674
+ await vm.fs.writeFile(`${chunkDir}/${chunkName}`, content);
1656
1675
  const uploadedChunks = index + 1;
1657
1676
  if (chunkCount > 1) {
1658
1677
  const progressMessage = `VM ${vmId}: uploaded ${uploadedChunks}/${chunkCount} ${label} archive chunks`;
@@ -1668,14 +1687,63 @@ async function uploadArchiveInChunks(vm, vmId, archivePath, remoteArchivePath, l
1668
1687
  }
1669
1688
  index += 1;
1670
1689
  }
1690
+ if (archiveSize > 0) {
1691
+ await vm.fs.writeTextFile(`${chunkDir}/manifest`, `${chunkManifest.join("\n")}\n`);
1692
+ }
1671
1693
  await checkedExec(vm, archiveSize === 0
1672
1694
  ? `: > ${shellQuote(remoteArchivePath)} && rm -rf ${shellQuote(chunkDir)}`
1673
1695
  : [
1674
1696
  "set -e",
1675
- `rm -f ${shellQuote(remoteArchivePath)}`,
1676
- `for chunk in ${shellQuote(chunkDir)}/*.chunk.b64; do`,
1677
- ` base64 -d "$chunk" >> ${shellQuote(remoteArchivePath)}`,
1697
+ `chunk_dir=${shellQuote(chunkDir)}`,
1698
+ `remote_archive=${shellQuote(remoteArchivePath)}`,
1699
+ `manifest="$chunk_dir/manifest"`,
1700
+ "deadline=$(( $(date +%s) + 60 ))",
1701
+ "while :; do",
1702
+ " validation_error=",
1703
+ " validated_chunks=0",
1704
+ " if [ ! -f \"$manifest\" ]; then",
1705
+ " validation_error='missing chunk manifest'",
1706
+ " else",
1707
+ " actual_chunks=$(find \"$chunk_dir\" -maxdepth 1 -type f -name '*.chunk' | wc -l | tr -d '[:space:]')",
1708
+ ` if [ "$actual_chunks" != ${shellQuote(String(chunkCount))} ]; then`,
1709
+ ` validation_error="expected ${chunkCount} chunks, found $actual_chunks"`,
1710
+ " else",
1711
+ " while IFS=' ' read -r chunk_name expected_size; do",
1712
+ " [ -n \"$chunk_name\" ] || continue",
1713
+ " chunk_path=\"$chunk_dir/$chunk_name\"",
1714
+ " if [ ! -f \"$chunk_path\" ]; then",
1715
+ " validation_error=\"missing chunk $chunk_name\"",
1716
+ " break",
1717
+ " fi",
1718
+ " actual_chunk_size=$(wc -c < \"$chunk_path\" | tr -d '[:space:]')",
1719
+ " if [ \"$actual_chunk_size\" != \"$expected_size\" ]; then",
1720
+ " validation_error=\"chunk $chunk_name expected $expected_size bytes, got $actual_chunk_size\"",
1721
+ " break",
1722
+ " fi",
1723
+ " validated_chunks=$((validated_chunks + 1))",
1724
+ " done < \"$manifest\"",
1725
+ ` if [ "$validated_chunks" != ${shellQuote(String(chunkCount))} ] && [ -z "$validation_error" ]; then`,
1726
+ ` validation_error="expected ${chunkCount} manifest entries, found $validated_chunks"`,
1727
+ " fi",
1728
+ " fi",
1729
+ " fi",
1730
+ " if [ -z \"$validation_error\" ]; then",
1731
+ " break",
1732
+ " fi",
1733
+ " if [ \"$(date +%s)\" -ge \"$deadline\" ]; then",
1734
+ ` rm -f ${shellQuote(remoteArchivePath)}`,
1735
+ ` rm -rf ${shellQuote(chunkDir)}`,
1736
+ ` echo ${shellQuote(`archive chunk validation failed for ${label}`)} >&2`,
1737
+ " echo \"$validation_error\" >&2",
1738
+ " exit 1",
1739
+ " fi",
1740
+ " sleep 1",
1678
1741
  "done",
1742
+ `rm -f ${shellQuote(remoteArchivePath)}`,
1743
+ "while IFS=' ' read -r chunk_name expected_size; do",
1744
+ " [ -n \"$chunk_name\" ] || continue",
1745
+ " cat \"$chunk_dir/$chunk_name\" >> \"$remote_archive\"",
1746
+ "done < \"$manifest\"",
1679
1747
  `actual_size=$(wc -c < ${shellQuote(remoteArchivePath)} | tr -d '[:space:]')`,
1680
1748
  `actual_hash=$(sha256sum ${shellQuote(remoteArchivePath)} | awk '{print $1}')`,
1681
1749
  `if [ "$actual_size" != ${shellQuote(String(archiveSize))} ] || [ "$actual_hash" != ${shellQuote(archiveHash)} ]; then`,
@@ -1686,7 +1754,7 @@ async function uploadArchiveInChunks(vm, vmId, archivePath, remoteArchivePath, l
1686
1754
  " exit 1",
1687
1755
  "fi",
1688
1756
  `rm -rf ${shellQuote(chunkDir)}`,
1689
- ].join("\n"));
1757
+ ].join("\n"), 5 * 60 * MS_PER_SECOND);
1690
1758
  }
1691
1759
  async function mkdirRemote(vm, directories) {
1692
1760
  for (const chunk of chunkArray(directories, 50)) {
@@ -0,0 +1,127 @@
1
+ export type VmProviderName = "freestyle" | "apple-container";
2
+ export type CliOptions = {
3
+ projectRoot: string;
4
+ cachePath: string;
5
+ remoteProjectDir: string;
6
+ provider: VmProviderName;
7
+ name: string;
8
+ vmId?: string;
9
+ appleContainerImage: string;
10
+ idleTimeoutSeconds?: number;
11
+ yes: boolean;
12
+ dryRun: boolean;
13
+ disablePlugins: string[];
14
+ enablePlugins: string[];
15
+ resetPluginPrefs: boolean;
16
+ listPlugins: boolean;
17
+ includeAuth: boolean;
18
+ includeAgentContext: boolean;
19
+ includeGitDir: boolean;
20
+ includeAllCopilotWorkspaces: boolean;
21
+ snapshot: boolean;
22
+ skipSync: boolean;
23
+ install: boolean;
24
+ autoSsh: boolean;
25
+ envKeys: string[];
26
+ };
27
+ export type ContextCandidate = {
28
+ source: string;
29
+ remoteRoot: string;
30
+ label: string;
31
+ sensitive: boolean;
32
+ preferenceKey: string;
33
+ promptLabel: string;
34
+ };
35
+ export type RemoteVm = {
36
+ exec(args: {
37
+ command: string;
38
+ timeoutMs?: number;
39
+ }): Promise<{
40
+ stdout?: string | null;
41
+ stderr?: string | null;
42
+ statusCode?: number | null;
43
+ }>;
44
+ fs: {
45
+ writeFile(path: string, content: Buffer): Promise<void>;
46
+ writeTextFile(path: string, content: string): Promise<void>;
47
+ };
48
+ };
49
+ export type UploadArchiveInChunks = (vm: RemoteVm, vmId: string, archivePath: string, remoteArchivePath: string, label: string) => Promise<void>;
50
+ export type ExecFileAsync = (file: string, args: string[]) => Promise<{
51
+ stdout: string;
52
+ stderr: string;
53
+ }>;
54
+ export type PushvmPluginUtils = {
55
+ checkedExec(vm: RemoteVm, command: string, timeoutMs?: number): Promise<{
56
+ stdout?: string | null;
57
+ stderr?: string | null;
58
+ statusCode?: number | null;
59
+ }>;
60
+ createTar(args: string[]): Promise<void>;
61
+ uploadArchiveInChunks: UploadArchiveInChunks;
62
+ execFileAsync: ExecFileAsync;
63
+ shellQuote(value: string): string;
64
+ md5(value: string): string;
65
+ delay(ms: number): Promise<void>;
66
+ };
67
+ export type PushvmPluginContext = {
68
+ options: CliOptions;
69
+ utils: PushvmPluginUtils;
70
+ };
71
+ export type RemoteHookContext = PushvmPluginContext & {
72
+ vm: RemoteVm;
73
+ vmId: string;
74
+ };
75
+ export type EditorScheme = string;
76
+ export type EditorHookContext = RemoteHookContext & {
77
+ scheme: EditorScheme;
78
+ remoteWorkspaceUri: string;
79
+ };
80
+ export type ConnectHookContext = RemoteHookContext & {
81
+ contextCandidates: ContextCandidate[];
82
+ runBeforeOpenRemoteEditor(args: {
83
+ scheme: EditorScheme;
84
+ remoteWorkspaceUri: string;
85
+ }): Promise<string[]>;
86
+ runAfterOpenRemoteEditor(args: {
87
+ scheme: EditorScheme;
88
+ remoteWorkspaceUri: string;
89
+ }): Promise<string[]>;
90
+ };
91
+ export type ProjectSyncInclude = string | {
92
+ source: string;
93
+ target?: string;
94
+ };
95
+ export type ProjectSyncConfig = {
96
+ exclude?: string[];
97
+ include?: ProjectSyncInclude[];
98
+ };
99
+ export type PushvmPlugin = {
100
+ name: string;
101
+ collectEnvironment?(context: PushvmPluginContext): Record<string, string>;
102
+ discoverContextCandidates?(context: PushvmPluginContext): Promise<ContextCandidate[]> | ContextCandidate[];
103
+ configureProjectSync?(context: PushvmPluginContext): Promise<ProjectSyncConfig | void> | ProjectSyncConfig | void;
104
+ shouldSkipContextDirectory?(relativePath: string, name: string): boolean;
105
+ isProtectedRemotePath?(remotePath: string): boolean;
106
+ afterProjectSync?(context: RemoteHookContext): Promise<void> | void;
107
+ afterContextSync?(context: RemoteHookContext & {
108
+ changedRemotePaths: string[];
109
+ }): Promise<void> | void;
110
+ beforeSnapshot?(context: RemoteHookContext): Promise<void> | void;
111
+ afterSync?(context: RemoteHookContext & {
112
+ contextCandidates: ContextCandidate[];
113
+ }): Promise<string[] | void> | string[] | void;
114
+ connect?(context: ConnectHookContext): Promise<boolean | void> | boolean | void;
115
+ beforeOpenRemoteEditor?(context: EditorHookContext & {
116
+ contextCandidates: ContextCandidate[];
117
+ }): Promise<string[] | void> | string[] | void;
118
+ afterOpenRemoteEditor?(context: EditorHookContext & {
119
+ contextCandidates: ContextCandidate[];
120
+ }): Promise<string[] | void> | string[] | void;
121
+ };
122
+ export type PushvmConfig = {
123
+ plugins: PushvmPlugin[];
124
+ sync?: ProjectSyncConfig;
125
+ };
126
+ export declare function definePlugin(plugin: PushvmPlugin): PushvmPlugin;
127
+ export declare function defineConfig(config: PushvmConfig): PushvmConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "freestyle-sync",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "main": "dist/src/main.js",
6
6
  "exports": {
@@ -25,7 +25,9 @@
25
25
  "publish": "npm run check && npm run build && npm run publish:workspaces && npm run publish:root",
26
26
  "publish:root": "node scripts/publish-root.mjs",
27
27
  "publish:workspaces": "node scripts/publish-workspaces.mjs",
28
- "start": "node src/main.ts"
28
+ "start": "node src/main.ts",
29
+ "version:patch": "node scripts/version-workspaces.mjs patch",
30
+ "version:workspaces": "node scripts/version-workspaces.mjs"
29
31
  },
30
32
  "dependencies": {
31
33
  "dotenv": "^17.4.2",