@kodrunhq/claudefy 0.1.0

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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/dist/backup-manager/backup-manager.d.ts +6 -0
  4. package/dist/backup-manager/backup-manager.js +27 -0
  5. package/dist/backup-manager/backup-manager.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.js +296 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/config.d.ts +8 -0
  10. package/dist/commands/config.js +56 -0
  11. package/dist/commands/config.js.map +1 -0
  12. package/dist/commands/doctor.d.ts +14 -0
  13. package/dist/commands/doctor.js +64 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/hooks.d.ts +7 -0
  16. package/dist/commands/hooks.js +18 -0
  17. package/dist/commands/hooks.js.map +1 -0
  18. package/dist/commands/init.d.ts +13 -0
  19. package/dist/commands/init.js +66 -0
  20. package/dist/commands/init.js.map +1 -0
  21. package/dist/commands/join.d.ts +12 -0
  22. package/dist/commands/join.js +51 -0
  23. package/dist/commands/join.js.map +1 -0
  24. package/dist/commands/link.d.ts +12 -0
  25. package/dist/commands/link.js +34 -0
  26. package/dist/commands/link.js.map +1 -0
  27. package/dist/commands/machines.d.ts +6 -0
  28. package/dist/commands/machines.js +25 -0
  29. package/dist/commands/machines.js.map +1 -0
  30. package/dist/commands/override.d.ts +12 -0
  31. package/dist/commands/override.js +44 -0
  32. package/dist/commands/override.js.map +1 -0
  33. package/dist/commands/pull.d.ts +17 -0
  34. package/dist/commands/pull.js +220 -0
  35. package/dist/commands/pull.js.map +1 -0
  36. package/dist/commands/push.d.ts +14 -0
  37. package/dist/commands/push.js +175 -0
  38. package/dist/commands/push.js.map +1 -0
  39. package/dist/commands/status.d.ts +14 -0
  40. package/dist/commands/status.js +50 -0
  41. package/dist/commands/status.js.map +1 -0
  42. package/dist/config/config-manager.d.ts +22 -0
  43. package/dist/config/config-manager.js +118 -0
  44. package/dist/config/config-manager.js.map +1 -0
  45. package/dist/config/defaults.d.ts +7 -0
  46. package/dist/config/defaults.js +33 -0
  47. package/dist/config/defaults.js.map +1 -0
  48. package/dist/config/types.d.ts +25 -0
  49. package/dist/config/types.js +2 -0
  50. package/dist/config/types.js.map +1 -0
  51. package/dist/encryptor/encryptor.d.ts +10 -0
  52. package/dist/encryptor/encryptor.js +68 -0
  53. package/dist/encryptor/encryptor.js.map +1 -0
  54. package/dist/encryptor/passphrase.d.ts +7 -0
  55. package/dist/encryptor/passphrase.js +34 -0
  56. package/dist/encryptor/passphrase.js.map +1 -0
  57. package/dist/git-adapter/git-adapter.d.ts +19 -0
  58. package/dist/git-adapter/git-adapter.js +104 -0
  59. package/dist/git-adapter/git-adapter.js.map +1 -0
  60. package/dist/git-adapter/types.d.ts +14 -0
  61. package/dist/git-adapter/types.js +2 -0
  62. package/dist/git-adapter/types.js.map +1 -0
  63. package/dist/hook-manager/hook-manager.d.ts +11 -0
  64. package/dist/hook-manager/hook-manager.js +110 -0
  65. package/dist/hook-manager/hook-manager.js.map +1 -0
  66. package/dist/index.d.ts +2 -0
  67. package/dist/index.js +4 -0
  68. package/dist/index.js.map +1 -0
  69. package/dist/machine-registry/machine-registry.d.ts +16 -0
  70. package/dist/machine-registry/machine-registry.js +65 -0
  71. package/dist/machine-registry/machine-registry.js.map +1 -0
  72. package/dist/merger/merger.d.ts +10 -0
  73. package/dist/merger/merger.js +15 -0
  74. package/dist/merger/merger.js.map +1 -0
  75. package/dist/output.d.ts +8 -0
  76. package/dist/output.js +10 -0
  77. package/dist/output.js.map +1 -0
  78. package/dist/path-mapper/git-identity.d.ts +8 -0
  79. package/dist/path-mapper/git-identity.js +35 -0
  80. package/dist/path-mapper/git-identity.js.map +1 -0
  81. package/dist/path-mapper/path-mapper.d.ts +19 -0
  82. package/dist/path-mapper/path-mapper.js +101 -0
  83. package/dist/path-mapper/path-mapper.js.map +1 -0
  84. package/dist/repo-creator/repo-creator.d.ts +6 -0
  85. package/dist/repo-creator/repo-creator.js +52 -0
  86. package/dist/repo-creator/repo-creator.js.map +1 -0
  87. package/dist/secret-scanner/scanner.d.ts +10 -0
  88. package/dist/secret-scanner/scanner.js +48 -0
  89. package/dist/secret-scanner/scanner.js.map +1 -0
  90. package/dist/sync-filter/sync-filter.d.ts +8 -0
  91. package/dist/sync-filter/sync-filter.js +37 -0
  92. package/dist/sync-filter/sync-filter.js.map +1 -0
  93. package/dist/sync-filter/types.d.ts +13 -0
  94. package/dist/sync-filter/types.js +2 -0
  95. package/dist/sync-filter/types.js.map +1 -0
  96. package/package.json +72 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kodrunhq
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # claudefy
2
+
3
+ Sync your Claude Code environment across machines.
4
+
5
+ ## What It Does
6
+
7
+ claudefy syncs your `~/.claude` directory (commands, skills, agents, hooks, rules, plans, plugins, settings, and project configs) across multiple machines using a private git repository as the backend. It handles:
8
+
9
+ - **Selective sync** — three-tier filter (allow/deny/unknown) controls what syncs
10
+ - **Encryption** — sensitive and unknown files encrypted with age before push
11
+ - **Path remapping** — machine-specific paths normalized to canonical IDs
12
+ - **Deep merge** — settings.json merged at the key level; other files use last-write-wins
13
+ - **Override** — wipe remote and push local as source of truth when needed
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install -g claudefy
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ **First machine (initialize):**
24
+
25
+ ```bash
26
+ # Create a private repo (requires gh or glab CLI)
27
+ claudefy init --backend git@github.com:you/claude-sync.git
28
+
29
+ # Or auto-create a GitHub repo
30
+ claudefy init --create-repo
31
+ ```
32
+
33
+ **Second machine (join):**
34
+
35
+ ```bash
36
+ claudefy join --backend git@github.com:you/claude-sync.git
37
+ ```
38
+
39
+ **Daily use:**
40
+
41
+ ```bash
42
+ claudefy push # Push local changes to remote
43
+ claudefy pull # Pull remote changes to local
44
+ claudefy status # Show sync status
45
+ ```
46
+
47
+ ## Commands
48
+
49
+ ### Core Sync
50
+
51
+ | Command | Description |
52
+ |---------|-------------|
53
+ | `claudefy init --backend <url>` | Initialize store on first machine |
54
+ | `claudefy join --backend <url>` | Join store from another machine |
55
+ | `claudefy push` | Push local state to remote |
56
+ | `claudefy pull` | Pull remote state to local |
57
+ | `claudefy override --confirm` | Wipe remote, push local as source of truth |
58
+ | `claudefy status` | Show file classification and sync state |
59
+
60
+ ### Project Mapping
61
+
62
+ | Command | Description |
63
+ |---------|-------------|
64
+ | `claudefy link <alias> <path>` | Map a local project path to a canonical ID |
65
+ | `claudefy unlink <alias>` | Remove a project mapping |
66
+ | `claudefy links` | List all project mappings |
67
+
68
+ ### Configuration
69
+
70
+ | Command | Description |
71
+ |---------|-------------|
72
+ | `claudefy config get [key]` | Show config or a specific key |
73
+ | `claudefy config set <key> <value>` | Update a config value |
74
+ | `claudefy doctor` | Diagnose sync health |
75
+ | `claudefy machines` | List registered machines |
76
+
77
+ ### Hooks
78
+
79
+ | Command | Description |
80
+ |---------|-------------|
81
+ | `claudefy hooks install` | Install auto-sync hooks (push on SessionEnd, pull on SessionStart) |
82
+ | `claudefy hooks remove` | Remove auto-sync hooks |
83
+
84
+ ### Options
85
+
86
+ Pass `--hooks` to `init` or `join` to install auto-sync hooks automatically.
87
+
88
+ ## Global Options
89
+
90
+ | Option | Description |
91
+ |--------|-------------|
92
+ | `-q, --quiet` | Suppress output |
93
+ | `--skip-encryption` | Skip encryption (for testing) |
94
+ | `--passphrase <passphrase>` | Encryption passphrase (prefer `CLAUDEFY_PASSPHRASE` env var) |
95
+
96
+ ## Encryption
97
+
98
+ claudefy encrypts files using [age](https://age-encryption.org/) (WASM-based, no native binary needed).
99
+
100
+ **Passphrase resolution order:**
101
+ 1. `--passphrase` CLI flag (highest priority; avoid — visible in process list)
102
+ 2. `CLAUDEFY_PASSPHRASE` environment variable
103
+ 3. OS keychain (requires `keytar`: `npm install -g keytar`)
104
+
105
+ **What gets encrypted:**
106
+ - Files in the "unknown" tier (not in allowlist or denylist) are always encrypted
107
+ - Allowlisted files can optionally be encrypted via config
108
+
109
+ ## How It Works
110
+
111
+ 1. **Sync filter** classifies each entry in `~/.claude` as allow, deny, or unknown
112
+ 2. **Push**: copies allowed files to git store, encrypts unknowns, normalizes paths, commits and pushes
113
+ 3. **Pull**: fetches from remote, decrypts, remaps paths to local machine, merges (deep merge for JSON, LWW for others)
114
+ 4. **Path remapping**: project directories use canonical IDs derived from git remotes (e.g., `github.com--owner--repo`)
115
+
116
+ ## Configuration
117
+
118
+ Config lives at `~/.claudefy/config.json`:
119
+
120
+ ```json
121
+ {
122
+ "version": 1,
123
+ "backend": { "type": "git", "url": "git@github.com:you/claude-sync.git" },
124
+ "encryption": { "enabled": true, "useKeychain": false, "cacheDuration": "0" },
125
+ "sync": { "lfsThreshold": 524288 },
126
+ "filter": {},
127
+ "machineId": "hostname-abc12345"
128
+ }
129
+ ```
130
+
131
+ Modify via `claudefy config set`:
132
+
133
+ ```bash
134
+ claudefy config set encryption.enabled false
135
+ claudefy config set encryption.useKeychain true
136
+ ```
137
+
138
+ ## Security
139
+
140
+ - Passphrases never stored in plain text on disk
141
+ - Secret scanner detects API keys, tokens, and high-entropy strings before push
142
+ - Unknown files always encrypted — never pushed in cleartext
143
+ - `--passphrase` CLI flag warns about process list exposure
144
+
145
+ ## License
146
+
147
+ MIT
@@ -0,0 +1,6 @@
1
+ export declare class BackupManager {
2
+ private backupsDir;
3
+ constructor(claudefyDir: string);
4
+ createBackup(claudeDir: string, label: string): Promise<string>;
5
+ listBackups(): Promise<string[]>;
6
+ }
@@ -0,0 +1,27 @@
1
+ import { cp, mkdir, readdir } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ export class BackupManager {
4
+ backupsDir;
5
+ constructor(claudefyDir) {
6
+ this.backupsDir = join(claudefyDir, "backups");
7
+ }
8
+ async createBackup(claudeDir, label) {
9
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
10
+ const safeLabel = label.replace(/[^a-zA-Z0-9._-]/g, "_");
11
+ const backupName = `${timestamp}--${safeLabel}`;
12
+ const backupPath = join(this.backupsDir, backupName);
13
+ await mkdir(backupPath, { recursive: true });
14
+ await cp(claudeDir, backupPath, { recursive: true });
15
+ return backupPath;
16
+ }
17
+ async listBackups() {
18
+ try {
19
+ const entries = await readdir(this.backupsDir);
20
+ return entries.sort().reverse();
21
+ }
22
+ catch {
23
+ return [];
24
+ }
25
+ }
26
+ }
27
+ //# sourceMappingURL=backup-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-manager.js","sourceRoot":"","sources":["../../src/backup-manager/backup-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,OAAO,aAAa;IAChB,UAAU,CAAS;IAE3B,YAAY,WAAmB;QAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,KAAa;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACzD,MAAM,UAAU,GAAG,GAAG,SAAS,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAErD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/C,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ declare const program: Command;
3
+ export { program };
package/dist/cli.js ADDED
@@ -0,0 +1,296 @@
1
+ import { Command } from "commander";
2
+ import { createRequire } from "node:module";
3
+ import { homedir } from "node:os";
4
+ import { output } from "./output.js";
5
+ const require = createRequire(import.meta.url);
6
+ const pkg = require("../package.json");
7
+ const program = new Command();
8
+ const homeDir = homedir();
9
+ function getGlobalOpts(cmd) {
10
+ const opts = cmd.optsWithGlobals();
11
+ return {
12
+ quiet: opts.quiet ?? false,
13
+ skipEncryption: opts.skipEncryption ?? false,
14
+ skipSecretScan: opts.skipSecretScan ?? false,
15
+ passphrase: process.env.CLAUDEFY_PASSPHRASE,
16
+ };
17
+ }
18
+ program
19
+ .name("claudefy")
20
+ .description("Sync your Claude Code environment across machines")
21
+ .version(pkg.version)
22
+ .option("-q, --quiet", "Suppress output")
23
+ .option("--skip-encryption", "Skip encryption")
24
+ .option("--skip-secret-scan", "Skip secret scanning on push");
25
+ program
26
+ .command("init")
27
+ .description("Initialize claudefy store on first machine")
28
+ .option("--backend <url>", "Git remote URL for store")
29
+ .option("--create-repo", "Auto-create a GitHub/GitLab repo")
30
+ .option("--hooks", "Install auto-sync hooks")
31
+ .action(async function (options) {
32
+ try {
33
+ const global = getGlobalOpts(this);
34
+ const { InitCommand } = await import("./commands/init.js");
35
+ const cmd = new InitCommand(homeDir);
36
+ await cmd.execute({
37
+ backend: options.backend,
38
+ quiet: global.quiet,
39
+ skipEncryption: global.skipEncryption,
40
+ passphrase: global.passphrase,
41
+ installHooks: options.hooks ?? false,
42
+ createRepo: options.createRepo ?? false,
43
+ });
44
+ }
45
+ catch (err) {
46
+ output.error(err instanceof Error ? err.message : String(err));
47
+ process.exit(1);
48
+ }
49
+ });
50
+ program
51
+ .command("join")
52
+ .description("Join existing claudefy store from another machine")
53
+ .requiredOption("--backend <url>", "Git remote URL for store")
54
+ .option("--hooks", "Install auto-sync hooks")
55
+ .action(async function (options) {
56
+ try {
57
+ const global = getGlobalOpts(this);
58
+ const { JoinCommand } = await import("./commands/join.js");
59
+ const cmd = new JoinCommand(homeDir);
60
+ await cmd.execute({
61
+ backend: options.backend,
62
+ quiet: global.quiet,
63
+ skipEncryption: global.skipEncryption,
64
+ passphrase: global.passphrase,
65
+ installHooks: options.hooks ?? false,
66
+ });
67
+ }
68
+ catch (err) {
69
+ output.error(err instanceof Error ? err.message : String(err));
70
+ process.exit(1);
71
+ }
72
+ });
73
+ program
74
+ .command("push")
75
+ .description("Push local state to remote store")
76
+ .action(async function () {
77
+ try {
78
+ const global = getGlobalOpts(this);
79
+ const { PushCommand } = await import("./commands/push.js");
80
+ const cmd = new PushCommand(homeDir);
81
+ await cmd.execute({
82
+ quiet: global.quiet,
83
+ skipEncryption: global.skipEncryption,
84
+ skipSecretScan: global.skipSecretScan,
85
+ passphrase: global.passphrase,
86
+ });
87
+ }
88
+ catch (err) {
89
+ output.error(err instanceof Error ? err.message : String(err));
90
+ process.exit(1);
91
+ }
92
+ });
93
+ program
94
+ .command("pull")
95
+ .description("Pull remote state to local machine")
96
+ .action(async function () {
97
+ try {
98
+ const global = getGlobalOpts(this);
99
+ const { PullCommand } = await import("./commands/pull.js");
100
+ const cmd = new PullCommand(homeDir);
101
+ await cmd.execute({
102
+ quiet: global.quiet,
103
+ skipEncryption: global.skipEncryption,
104
+ passphrase: global.passphrase,
105
+ });
106
+ }
107
+ catch (err) {
108
+ output.error(err instanceof Error ? err.message : String(err));
109
+ process.exit(1);
110
+ }
111
+ });
112
+ program
113
+ .command("override")
114
+ .description("Wipe remote and push local as source of truth")
115
+ .option("--confirm", "Confirm destructive override")
116
+ .action(async function (options) {
117
+ try {
118
+ const global = getGlobalOpts(this);
119
+ const { OverrideCommand } = await import("./commands/override.js");
120
+ const cmd = new OverrideCommand(homeDir);
121
+ await cmd.execute({
122
+ quiet: global.quiet,
123
+ skipEncryption: global.skipEncryption,
124
+ passphrase: global.passphrase,
125
+ confirm: options.confirm ?? false,
126
+ });
127
+ }
128
+ catch (err) {
129
+ output.error(err instanceof Error ? err.message : String(err));
130
+ process.exit(1);
131
+ }
132
+ });
133
+ program
134
+ .command("status")
135
+ .description("Show diff between local and remote")
136
+ .action(async function () {
137
+ try {
138
+ const { StatusCommand } = await import("./commands/status.js");
139
+ const cmd = new StatusCommand(homeDir);
140
+ const result = await cmd.execute();
141
+ console.log(JSON.stringify(result, null, 2));
142
+ }
143
+ catch (err) {
144
+ output.error(err instanceof Error ? err.message : String(err));
145
+ process.exit(1);
146
+ }
147
+ });
148
+ program
149
+ .command("link <alias> <path>")
150
+ .description("Map local path to canonical project ID")
151
+ .action(async (alias, localPath) => {
152
+ try {
153
+ const { LinkCommand } = await import("./commands/link.js");
154
+ const cmd = new LinkCommand(homeDir);
155
+ await cmd.add(alias, localPath);
156
+ }
157
+ catch (err) {
158
+ output.error(err instanceof Error ? err.message : String(err));
159
+ process.exit(1);
160
+ }
161
+ });
162
+ program
163
+ .command("unlink <alias>")
164
+ .description("Remove project mapping")
165
+ .action(async (alias) => {
166
+ try {
167
+ const { LinkCommand } = await import("./commands/link.js");
168
+ const cmd = new LinkCommand(homeDir);
169
+ await cmd.remove(alias);
170
+ }
171
+ catch (err) {
172
+ output.error(err instanceof Error ? err.message : String(err));
173
+ process.exit(1);
174
+ }
175
+ });
176
+ program
177
+ .command("links")
178
+ .description("List all project mappings")
179
+ .action(async () => {
180
+ try {
181
+ const { LinkCommand } = await import("./commands/link.js");
182
+ const cmd = new LinkCommand(homeDir);
183
+ const links = await cmd.list();
184
+ console.log(JSON.stringify(links, null, 2));
185
+ }
186
+ catch (err) {
187
+ output.error(err instanceof Error ? err.message : String(err));
188
+ process.exit(1);
189
+ }
190
+ });
191
+ program
192
+ .command("machines")
193
+ .description("List registered machines")
194
+ .action(async () => {
195
+ try {
196
+ const { MachinesCommand } = await import("./commands/machines.js");
197
+ const cmd = new MachinesCommand(homeDir);
198
+ const machines = await cmd.execute();
199
+ console.log(JSON.stringify(machines, null, 2));
200
+ }
201
+ catch (err) {
202
+ output.error(err instanceof Error ? err.message : String(err));
203
+ process.exit(1);
204
+ }
205
+ });
206
+ const configCmd = program.command("config").description("Manage claudefy configuration");
207
+ configCmd
208
+ .command("get [key]")
209
+ .description("Show full config or a specific key")
210
+ .action(async (key) => {
211
+ try {
212
+ const { ConfigCommand } = await import("./commands/config.js");
213
+ const cmd = new ConfigCommand(homeDir);
214
+ const result = await cmd.get(key);
215
+ console.log(typeof result === "object" ? JSON.stringify(result, null, 2) : String(result));
216
+ }
217
+ catch (err) {
218
+ output.error(err instanceof Error ? err.message : String(err));
219
+ process.exit(1);
220
+ }
221
+ });
222
+ configCmd
223
+ .command("set <key> <value>")
224
+ .description("Update a config value")
225
+ .action(async (key, value) => {
226
+ try {
227
+ const { ConfigCommand } = await import("./commands/config.js");
228
+ const cmd = new ConfigCommand(homeDir);
229
+ await cmd.set(key, value);
230
+ output.success(`Set ${key}`);
231
+ }
232
+ catch (err) {
233
+ output.error(err instanceof Error ? err.message : String(err));
234
+ process.exit(1);
235
+ }
236
+ });
237
+ program
238
+ .command("doctor")
239
+ .description("Diagnose sync health")
240
+ .action(async () => {
241
+ try {
242
+ const { DoctorCommand } = await import("./commands/doctor.js");
243
+ const cmd = new DoctorCommand(homeDir);
244
+ const checks = await cmd.execute();
245
+ for (const check of checks) {
246
+ if (check.status === "pass") {
247
+ output.success(`${check.name}: ${check.detail}`);
248
+ }
249
+ else if (check.status === "warn") {
250
+ output.warn(`${check.name}: ${check.detail}`);
251
+ }
252
+ else {
253
+ output.error(`${check.name}: ${check.detail}`);
254
+ }
255
+ }
256
+ const failures = checks.filter((c) => c.status === "fail");
257
+ if (failures.length > 0) {
258
+ process.exit(1);
259
+ }
260
+ }
261
+ catch (err) {
262
+ output.error(err instanceof Error ? err.message : String(err));
263
+ process.exit(1);
264
+ }
265
+ });
266
+ const hooksCmd = program.command("hooks").description("Manage auto-sync hooks");
267
+ hooksCmd
268
+ .command("install")
269
+ .description("Install auto-sync hooks")
270
+ .action(async () => {
271
+ try {
272
+ const { HooksCommand } = await import("./commands/hooks.js");
273
+ const cmd = new HooksCommand(homeDir);
274
+ await cmd.install();
275
+ }
276
+ catch (err) {
277
+ output.error(err instanceof Error ? err.message : String(err));
278
+ process.exit(1);
279
+ }
280
+ });
281
+ hooksCmd
282
+ .command("remove")
283
+ .description("Remove auto-sync hooks")
284
+ .action(async () => {
285
+ try {
286
+ const { HooksCommand } = await import("./commands/hooks.js");
287
+ const cmd = new HooksCommand(homeDir);
288
+ await cmd.remove();
289
+ }
290
+ catch (err) {
291
+ output.error(err instanceof Error ? err.message : String(err));
292
+ process.exit(1);
293
+ }
294
+ });
295
+ export { program };
296
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare class ConfigCommand {
2
+ private homeDir;
3
+ constructor(homeDir: string);
4
+ get(key?: string): Promise<unknown>;
5
+ private static readonly FORBIDDEN_KEYS;
6
+ set(key: string, value: unknown): Promise<void>;
7
+ private parseValue;
8
+ }
@@ -0,0 +1,56 @@
1
+ import { ConfigManager } from "../config/config-manager.js";
2
+ export class ConfigCommand {
3
+ homeDir;
4
+ constructor(homeDir) {
5
+ this.homeDir = homeDir;
6
+ }
7
+ async get(key) {
8
+ const configManager = new ConfigManager(this.homeDir);
9
+ if (!configManager.isInitialized()) {
10
+ throw new Error("claudefy is not initialized. Run 'claudefy init' first.");
11
+ }
12
+ const config = await configManager.load();
13
+ if (!key)
14
+ return config;
15
+ const parts = key.split(".");
16
+ let current = config;
17
+ for (const part of parts) {
18
+ if (current === null || current === undefined || typeof current !== "object") {
19
+ throw new Error(`Invalid config key: "${key}"`);
20
+ }
21
+ current = current[part];
22
+ if (current === undefined) {
23
+ throw new Error(`Invalid config key: "${key}"`);
24
+ }
25
+ }
26
+ return current;
27
+ }
28
+ static FORBIDDEN_KEYS = new Set(["__proto__", "prototype", "constructor"]);
29
+ async set(key, value) {
30
+ const configManager = new ConfigManager(this.homeDir);
31
+ if (!configManager.isInitialized()) {
32
+ throw new Error("claudefy is not initialized. Run 'claudefy init' first.");
33
+ }
34
+ const parts = key.split(".");
35
+ for (const part of parts) {
36
+ if (ConfigCommand.FORBIDDEN_KEYS.has(part)) {
37
+ throw new Error(`Invalid config key: "${key}" — "${part}" is not allowed`);
38
+ }
39
+ }
40
+ const parsed = this.parseValue(value);
41
+ await configManager.set(key, parsed);
42
+ }
43
+ parseValue(value) {
44
+ if (typeof value !== "string")
45
+ return value;
46
+ if (value === "true")
47
+ return true;
48
+ if (value === "false")
49
+ return false;
50
+ const num = Number(value);
51
+ if (!isNaN(num) && value.trim() !== "")
52
+ return num;
53
+ return value;
54
+ }
55
+ }
56
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,OAAO,aAAa;IAChB,OAAO,CAAS;IAExB,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAY;QACpB,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,CAAC;QAE1C,IAAI,CAAC,GAAG;YAAE,OAAO,MAAM,CAAC;QAExB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,OAAO,GAAY,MAAM,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC7E,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,GAAI,OAAmC,CAAC,IAAI,CAAC,CAAC;YACrD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,GAAG,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,MAAM,CAAU,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;IAE5F,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAc;QACnC,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,QAAQ,IAAI,kBAAkB,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAEO,UAAU,CAAC,KAAc;QAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,KAAK,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,KAAK,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,GAAG,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface DoctorCheck {
2
+ name: string;
3
+ status: "pass" | "fail" | "warn";
4
+ detail: string;
5
+ }
6
+ export declare class DoctorCommand {
7
+ private homeDir;
8
+ constructor(homeDir: string);
9
+ execute(): Promise<DoctorCheck[]>;
10
+ private checkBinary;
11
+ private checkInitialized;
12
+ private checkEncryption;
13
+ private checkRemote;
14
+ }