@drewpayment/mink 0.3.0 → 0.4.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.
- package/README.md +80 -11
- package/dist/cli.js +583 -320
- package/package.json +1 -1
- package/src/cli.ts +10 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/device.ts +65 -0
- package/src/commands/session-start.ts +16 -0
- package/src/core/device.ts +72 -0
- package/src/core/global-config.ts +72 -11
- package/src/core/paths.ts +12 -0
- package/src/core/sync.ts +12 -0
- package/src/types/config.ts +25 -0
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -143,6 +143,12 @@ switch (command) {
|
|
|
143
143
|
break;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
case "device": {
|
|
147
|
+
const { device } = await import("./commands/device");
|
|
148
|
+
device(process.argv.slice(3));
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
|
|
146
152
|
case "bug-search": {
|
|
147
153
|
const { bugSearch } = await import("./commands/bug-search");
|
|
148
154
|
bugSearch(cwd, process.argv.slice(3).join(" "));
|
|
@@ -202,7 +208,10 @@ switch (command) {
|
|
|
202
208
|
console.log(" note search <term> Full-text search across the vault");
|
|
203
209
|
console.log(" skill install Install /mink:note skill for Claude Code");
|
|
204
210
|
console.log();
|
|
205
|
-
console.log("Sync:");
|
|
211
|
+
console.log("Devices & Sync:");
|
|
212
|
+
console.log(" device Show current device info");
|
|
213
|
+
console.log(" device list List all registered devices");
|
|
214
|
+
console.log(" device rename <name> Set a friendly name for this device");
|
|
206
215
|
console.log(" sync Full manual sync (pull then push)");
|
|
207
216
|
console.log(" sync init <remote-url> Connect ~/.mink to a git remote for cross-device sync");
|
|
208
217
|
console.log(" sync status Show sync state (remote, last sync, pending changes)");
|
package/src/commands/config.ts
CHANGED
|
@@ -69,7 +69,7 @@ export async function config(args: string[]): Promise<void> {
|
|
|
69
69
|
const all = resolveAllConfig();
|
|
70
70
|
console.log("[mink] configuration:");
|
|
71
71
|
for (const entry of all) {
|
|
72
|
-
let line = ` ${entry.key} = ${entry.value} (source: ${entry.source})`;
|
|
72
|
+
let line = ` ${entry.key} = ${entry.value} (${entry.scope}, source: ${entry.source})`;
|
|
73
73
|
if (
|
|
74
74
|
entry.source === "environment variable" &&
|
|
75
75
|
entry.configFileValue !== undefined
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getOrCreateDeviceId,
|
|
3
|
+
listDevices,
|
|
4
|
+
setDeviceName,
|
|
5
|
+
} from "../core/device";
|
|
6
|
+
import { hostname, platform } from "os";
|
|
7
|
+
|
|
8
|
+
export function device(args: string[]): void {
|
|
9
|
+
const sub = args[0] ?? "status";
|
|
10
|
+
|
|
11
|
+
switch (sub) {
|
|
12
|
+
case "status": {
|
|
13
|
+
const id = getOrCreateDeviceId();
|
|
14
|
+
const devices = listDevices();
|
|
15
|
+
const current = devices.find((d) => d.id === id);
|
|
16
|
+
console.log("[mink] device info:");
|
|
17
|
+
console.log(` id: ${id}`);
|
|
18
|
+
console.log(` name: ${current?.name ?? hostname()}`);
|
|
19
|
+
console.log(` hostname: ${hostname()}`);
|
|
20
|
+
console.log(` platform: ${platform()}`);
|
|
21
|
+
if (current?.firstSeen) {
|
|
22
|
+
console.log(` first seen: ${current.firstSeen}`);
|
|
23
|
+
}
|
|
24
|
+
if (current?.lastSeen) {
|
|
25
|
+
console.log(` last seen: ${current.lastSeen}`);
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
case "list": {
|
|
31
|
+
const devices = listDevices();
|
|
32
|
+
const currentId = getOrCreateDeviceId();
|
|
33
|
+
if (devices.length === 0) {
|
|
34
|
+
console.log("[mink] no devices registered yet");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
console.log("[mink] registered devices:");
|
|
38
|
+
for (const d of devices) {
|
|
39
|
+
const marker = d.id === currentId ? " (this device)" : "";
|
|
40
|
+
console.log(` ${d.name}${marker}`);
|
|
41
|
+
console.log(` id: ${d.id}`);
|
|
42
|
+
console.log(` hostname: ${d.hostname}`);
|
|
43
|
+
console.log(` platform: ${d.platform}`);
|
|
44
|
+
console.log(` last seen: ${d.lastSeen}`);
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
case "rename": {
|
|
50
|
+
const name = args.slice(1).join(" ");
|
|
51
|
+
if (!name) {
|
|
52
|
+
console.error("Usage: mink device rename <name>");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
setDeviceName(name);
|
|
56
|
+
console.log(`[mink] device renamed to "${name}"`);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
default:
|
|
61
|
+
console.error(`[mink] unknown device subcommand: ${sub}`);
|
|
62
|
+
console.error("Usage: mink device [status|list|rename <name>]");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -7,6 +7,22 @@ import { isWikiEnabled, isVaultInitialized, isInsideVault } from "../core/vault"
|
|
|
7
7
|
import { loadVaultIndex } from "../core/note-index";
|
|
8
8
|
|
|
9
9
|
export function sessionStart(cwd: string): void {
|
|
10
|
+
// Migrate config to shared/local split if needed (before sync pull)
|
|
11
|
+
try {
|
|
12
|
+
const { migrateConfigIfNeeded } = require("../core/global-config");
|
|
13
|
+
migrateConfigIfNeeded();
|
|
14
|
+
} catch {
|
|
15
|
+
// Never crash hooks
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Register/update this device in the registry
|
|
19
|
+
try {
|
|
20
|
+
const { updateDeviceHeartbeat } = require("../core/device");
|
|
21
|
+
updateDeviceHeartbeat();
|
|
22
|
+
} catch {
|
|
23
|
+
// Never crash hooks
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
// Sync pull before session begins (if enabled)
|
|
11
27
|
try {
|
|
12
28
|
const { isSyncInitialized, syncPull } = require("../core/sync");
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { dirname } from "path";
|
|
3
|
+
import { hostname, platform } from "os";
|
|
4
|
+
import { randomUUID } from "crypto";
|
|
5
|
+
import { deviceIdPath, deviceRegistryPath } from "./paths";
|
|
6
|
+
import { safeReadJson, atomicWriteJson } from "./fs-utils";
|
|
7
|
+
import type { DeviceInfo, DeviceRegistry } from "../types/config";
|
|
8
|
+
|
|
9
|
+
export function getOrCreateDeviceId(): string {
|
|
10
|
+
const idPath = deviceIdPath();
|
|
11
|
+
if (existsSync(idPath)) {
|
|
12
|
+
return readFileSync(idPath, "utf-8").trim();
|
|
13
|
+
}
|
|
14
|
+
const id = randomUUID();
|
|
15
|
+
mkdirSync(dirname(idPath), { recursive: true });
|
|
16
|
+
writeFileSync(idPath, id + "\n");
|
|
17
|
+
return id;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function loadDeviceRegistry(): DeviceRegistry {
|
|
21
|
+
const raw = safeReadJson(deviceRegistryPath());
|
|
22
|
+
if (raw !== null && typeof raw === "object" && !Array.isArray(raw) && "devices" in (raw as object)) {
|
|
23
|
+
return raw as DeviceRegistry;
|
|
24
|
+
}
|
|
25
|
+
return { devices: {} };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function saveDeviceRegistry(registry: DeviceRegistry): void {
|
|
29
|
+
atomicWriteJson(deviceRegistryPath(), registry);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function updateDeviceHeartbeat(): void {
|
|
33
|
+
const id = getOrCreateDeviceId();
|
|
34
|
+
const registry = loadDeviceRegistry();
|
|
35
|
+
const now = new Date().toISOString();
|
|
36
|
+
const existing = registry.devices[id];
|
|
37
|
+
|
|
38
|
+
registry.devices[id] = {
|
|
39
|
+
name: existing?.name ?? hostname(),
|
|
40
|
+
hostname: hostname(),
|
|
41
|
+
platform: platform(),
|
|
42
|
+
firstSeen: existing?.firstSeen ?? now,
|
|
43
|
+
lastSeen: now,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
saveDeviceRegistry(registry);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function listDevices(): Array<DeviceInfo & { id: string }> {
|
|
50
|
+
const registry = loadDeviceRegistry();
|
|
51
|
+
return Object.entries(registry.devices).map(([id, info]) => ({
|
|
52
|
+
id,
|
|
53
|
+
...info,
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function setDeviceName(name: string): void {
|
|
58
|
+
const id = getOrCreateDeviceId();
|
|
59
|
+
const registry = loadDeviceRegistry();
|
|
60
|
+
const now = new Date().toISOString();
|
|
61
|
+
const existing = registry.devices[id];
|
|
62
|
+
|
|
63
|
+
registry.devices[id] = {
|
|
64
|
+
name,
|
|
65
|
+
hostname: hostname(),
|
|
66
|
+
platform: platform(),
|
|
67
|
+
firstSeen: existing?.firstSeen ?? now,
|
|
68
|
+
lastSeen: now,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
saveDeviceRegistry(registry);
|
|
72
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { globalConfigPath } from "./paths";
|
|
1
|
+
import { globalConfigPath, localConfigPath } from "./paths";
|
|
2
2
|
import { safeReadJson, atomicWriteJson } from "./fs-utils";
|
|
3
3
|
import {
|
|
4
4
|
CONFIG_KEYS,
|
|
@@ -6,31 +6,57 @@ import {
|
|
|
6
6
|
getConfigKeyMeta,
|
|
7
7
|
type GlobalConfig,
|
|
8
8
|
type ConfigKey,
|
|
9
|
+
type ConfigScope,
|
|
9
10
|
} from "../types/config";
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
const raw = safeReadJson(
|
|
12
|
+
function loadConfigFile(path: string): GlobalConfig {
|
|
13
|
+
const raw = safeReadJson(path);
|
|
13
14
|
if (raw === null) return {};
|
|
14
15
|
if (typeof raw !== "object" || Array.isArray(raw)) {
|
|
15
|
-
console.warn("[mink] warning: corrupt config file at " +
|
|
16
|
+
console.warn("[mink] warning: corrupt config file at " + path);
|
|
16
17
|
return {};
|
|
17
18
|
}
|
|
18
19
|
return raw as GlobalConfig;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
export function loadGlobalConfig(): GlobalConfig {
|
|
23
|
+
return loadConfigFile(globalConfigPath());
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
export function saveGlobalConfig(config: GlobalConfig): void {
|
|
22
27
|
atomicWriteJson(globalConfigPath(), config);
|
|
23
28
|
}
|
|
24
29
|
|
|
30
|
+
export function loadLocalConfig(): GlobalConfig {
|
|
31
|
+
return loadConfigFile(localConfigPath());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function saveLocalConfig(config: GlobalConfig): void {
|
|
35
|
+
atomicWriteJson(localConfigPath(), config);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function loadConfigForScope(scope: ConfigScope): GlobalConfig {
|
|
39
|
+
return scope === "local" ? loadLocalConfig() : loadGlobalConfig();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function saveConfigForScope(scope: ConfigScope, config: GlobalConfig): void {
|
|
43
|
+
if (scope === "local") {
|
|
44
|
+
saveLocalConfig(config);
|
|
45
|
+
} else {
|
|
46
|
+
saveGlobalConfig(config);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
25
50
|
export interface ResolvedValue {
|
|
26
51
|
value: string;
|
|
27
52
|
source: "default" | "config file" | "environment variable";
|
|
53
|
+
scope: ConfigScope;
|
|
28
54
|
configFileValue?: string;
|
|
29
55
|
}
|
|
30
56
|
|
|
31
57
|
export function resolveConfigValue(key: ConfigKey): ResolvedValue {
|
|
32
58
|
const meta = getConfigKeyMeta(key);
|
|
33
|
-
const config =
|
|
59
|
+
const config = loadConfigForScope(meta.scope);
|
|
34
60
|
|
|
35
61
|
const envValue = process.env[meta.envVar];
|
|
36
62
|
const fileValue = config[key];
|
|
@@ -39,15 +65,16 @@ export function resolveConfigValue(key: ConfigKey): ResolvedValue {
|
|
|
39
65
|
return {
|
|
40
66
|
value: envValue,
|
|
41
67
|
source: "environment variable",
|
|
68
|
+
scope: meta.scope,
|
|
42
69
|
configFileValue: fileValue,
|
|
43
70
|
};
|
|
44
71
|
}
|
|
45
72
|
|
|
46
73
|
if (fileValue !== undefined) {
|
|
47
|
-
return { value: fileValue, source: "config file" };
|
|
74
|
+
return { value: fileValue, source: "config file", scope: meta.scope };
|
|
48
75
|
}
|
|
49
76
|
|
|
50
|
-
return { value: meta.default, source: "default" };
|
|
77
|
+
return { value: meta.default, source: "default", scope: meta.scope };
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
export function resolveAllConfig(): Array<ResolvedValue & { key: ConfigKey }> {
|
|
@@ -58,17 +85,51 @@ export function resolveAllConfig(): Array<ResolvedValue & { key: ConfigKey }> {
|
|
|
58
85
|
}
|
|
59
86
|
|
|
60
87
|
export function setConfigValue(key: ConfigKey, value: string): void {
|
|
61
|
-
const
|
|
88
|
+
const meta = getConfigKeyMeta(key);
|
|
89
|
+
const config = loadConfigForScope(meta.scope);
|
|
62
90
|
config[key] = value;
|
|
63
|
-
|
|
91
|
+
saveConfigForScope(meta.scope, config);
|
|
64
92
|
}
|
|
65
93
|
|
|
66
94
|
export function resetConfigKey(key: ConfigKey): void {
|
|
67
|
-
const
|
|
95
|
+
const meta = getConfigKeyMeta(key);
|
|
96
|
+
const config = loadConfigForScope(meta.scope);
|
|
68
97
|
delete config[key];
|
|
69
|
-
|
|
98
|
+
saveConfigForScope(meta.scope, config);
|
|
70
99
|
}
|
|
71
100
|
|
|
72
101
|
export function resetAllConfig(): void {
|
|
73
102
|
saveGlobalConfig({});
|
|
103
|
+
saveLocalConfig({});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Migration ─────────────────────────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
let migrationRan = false;
|
|
109
|
+
|
|
110
|
+
export function migrateConfigIfNeeded(): void {
|
|
111
|
+
if (migrationRan) return;
|
|
112
|
+
migrationRan = true;
|
|
113
|
+
|
|
114
|
+
const { existsSync } = require("fs");
|
|
115
|
+
if (existsSync(localConfigPath())) return;
|
|
116
|
+
|
|
117
|
+
const shared = loadGlobalConfig();
|
|
118
|
+
const localKeys = CONFIG_KEYS.filter((k) => k.scope === "local");
|
|
119
|
+
const localConfig: GlobalConfig = {};
|
|
120
|
+
let hasLocal = false;
|
|
121
|
+
|
|
122
|
+
for (const meta of localKeys) {
|
|
123
|
+
const val = shared[meta.key];
|
|
124
|
+
if (val !== undefined) {
|
|
125
|
+
localConfig[meta.key] = val;
|
|
126
|
+
delete shared[meta.key];
|
|
127
|
+
hasLocal = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (hasLocal) {
|
|
132
|
+
saveLocalConfig(localConfig);
|
|
133
|
+
saveGlobalConfig(shared);
|
|
134
|
+
}
|
|
74
135
|
}
|
package/src/core/paths.ts
CHANGED
|
@@ -61,6 +61,18 @@ export function globalConfigPath(): string {
|
|
|
61
61
|
return join(MINK_ROOT, "config");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
export function localConfigPath(): string {
|
|
65
|
+
return join(MINK_ROOT, "config.local");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function deviceIdPath(): string {
|
|
69
|
+
return join(MINK_ROOT, "device-id");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function deviceRegistryPath(): string {
|
|
73
|
+
return join(MINK_ROOT, "devices.json");
|
|
74
|
+
}
|
|
75
|
+
|
|
64
76
|
export function projectMetaPath(cwd: string): string {
|
|
65
77
|
return join(projectDir(cwd), "project-meta.json");
|
|
66
78
|
}
|
package/src/core/sync.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from "path";
|
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
import { minkRoot } from "./paths";
|
|
5
5
|
import { resolveConfigValue, setConfigValue } from "./global-config";
|
|
6
|
+
import { updateDeviceHeartbeat } from "./device";
|
|
6
7
|
|
|
7
8
|
// ── Constants ──────────────────────────────────────────────────────────────
|
|
8
9
|
|
|
@@ -14,6 +15,10 @@ const GITIGNORE_CONTENTS = `# Runtime state — machine-specific
|
|
|
14
15
|
scheduler.pid
|
|
15
16
|
scheduler.log
|
|
16
17
|
|
|
18
|
+
# Device identity and local config — machine-specific
|
|
19
|
+
device-id
|
|
20
|
+
config.local
|
|
21
|
+
|
|
17
22
|
# Local backups — machine-specific snapshots
|
|
18
23
|
projects/*/backups/
|
|
19
24
|
`;
|
|
@@ -171,6 +176,8 @@ export function syncPull(
|
|
|
171
176
|
): void {
|
|
172
177
|
if (!isSyncInitialized()) return;
|
|
173
178
|
|
|
179
|
+
ensureGitignore();
|
|
180
|
+
|
|
174
181
|
const root = minkRoot();
|
|
175
182
|
|
|
176
183
|
try {
|
|
@@ -218,6 +225,8 @@ export function syncPull(
|
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
setConfigValue("sync.last-pull", new Date().toISOString());
|
|
228
|
+
|
|
229
|
+
try { updateDeviceHeartbeat(); } catch { /* never crash hooks */ }
|
|
221
230
|
} catch (err) {
|
|
222
231
|
onMessage(
|
|
223
232
|
`[mink] sync pull error: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -230,6 +239,9 @@ export function syncPush(
|
|
|
230
239
|
): void {
|
|
231
240
|
if (!isSyncInitialized()) return;
|
|
232
241
|
|
|
242
|
+
ensureGitignore();
|
|
243
|
+
try { updateDeviceHeartbeat(); } catch { /* never crash hooks */ }
|
|
244
|
+
|
|
233
245
|
const root = minkRoot();
|
|
234
246
|
|
|
235
247
|
try {
|
package/src/types/config.ts
CHANGED
|
@@ -13,11 +13,26 @@ export interface GlobalConfig {
|
|
|
13
13
|
|
|
14
14
|
export type ConfigKey = keyof GlobalConfig & string;
|
|
15
15
|
|
|
16
|
+
export type ConfigScope = "shared" | "local";
|
|
17
|
+
|
|
16
18
|
export interface ConfigKeyMeta {
|
|
17
19
|
key: ConfigKey;
|
|
18
20
|
default: string;
|
|
19
21
|
envVar: string;
|
|
20
22
|
description: string;
|
|
23
|
+
scope: ConfigScope;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DeviceInfo {
|
|
27
|
+
name: string;
|
|
28
|
+
hostname: string;
|
|
29
|
+
platform: string;
|
|
30
|
+
firstSeen: string;
|
|
31
|
+
lastSeen: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface DeviceRegistry {
|
|
35
|
+
devices: Record<string, DeviceInfo>;
|
|
21
36
|
}
|
|
22
37
|
|
|
23
38
|
export const CONFIG_KEYS: ConfigKeyMeta[] = [
|
|
@@ -26,60 +41,70 @@ export const CONFIG_KEYS: ConfigKeyMeta[] = [
|
|
|
26
41
|
default: "~/.mink/wiki/",
|
|
27
42
|
envVar: "MINK_WIKI_PATH",
|
|
28
43
|
description: "Wiki vault location",
|
|
44
|
+
scope: "local",
|
|
29
45
|
},
|
|
30
46
|
{
|
|
31
47
|
key: "wiki.enabled",
|
|
32
48
|
default: "true",
|
|
33
49
|
envVar: "MINK_WIKI_ENABLED",
|
|
34
50
|
description: "Enable/disable the wiki feature",
|
|
51
|
+
scope: "shared",
|
|
35
52
|
},
|
|
36
53
|
{
|
|
37
54
|
key: "wiki.sync-mode",
|
|
38
55
|
default: "immediate",
|
|
39
56
|
envVar: "MINK_WIKI_SYNC_MODE",
|
|
40
57
|
description: "Sync mode: immediate or batched",
|
|
58
|
+
scope: "shared",
|
|
41
59
|
},
|
|
42
60
|
{
|
|
43
61
|
key: "wiki.git-backup",
|
|
44
62
|
default: "false",
|
|
45
63
|
envVar: "MINK_WIKI_GIT_BACKUP",
|
|
46
64
|
description: "Deprecated: use sync.enabled instead",
|
|
65
|
+
scope: "shared",
|
|
47
66
|
},
|
|
48
67
|
{
|
|
49
68
|
key: "wiki.git-remote",
|
|
50
69
|
default: "origin",
|
|
51
70
|
envVar: "MINK_WIKI_GIT_REMOTE",
|
|
52
71
|
description: "Deprecated: use sync.remote-url instead",
|
|
72
|
+
scope: "shared",
|
|
53
73
|
},
|
|
54
74
|
{
|
|
55
75
|
key: "notes.default-category",
|
|
56
76
|
default: "inbox",
|
|
57
77
|
envVar: "MINK_NOTES_DEFAULT_CATEGORY",
|
|
58
78
|
description: "Default category for notes captured via CLI",
|
|
79
|
+
scope: "shared",
|
|
59
80
|
},
|
|
60
81
|
{
|
|
61
82
|
key: "sync.enabled",
|
|
62
83
|
default: "false",
|
|
63
84
|
envVar: "MINK_SYNC_ENABLED",
|
|
64
85
|
description: "Enable/disable automatic git sync of ~/.mink",
|
|
86
|
+
scope: "shared",
|
|
65
87
|
},
|
|
66
88
|
{
|
|
67
89
|
key: "sync.remote-url",
|
|
68
90
|
default: "",
|
|
69
91
|
envVar: "MINK_SYNC_REMOTE_URL",
|
|
70
92
|
description: "Git remote URL for ~/.mink sync",
|
|
93
|
+
scope: "shared",
|
|
71
94
|
},
|
|
72
95
|
{
|
|
73
96
|
key: "sync.last-push",
|
|
74
97
|
default: "",
|
|
75
98
|
envVar: "MINK_SYNC_LAST_PUSH",
|
|
76
99
|
description: "ISO timestamp of last successful sync push",
|
|
100
|
+
scope: "local",
|
|
77
101
|
},
|
|
78
102
|
{
|
|
79
103
|
key: "sync.last-pull",
|
|
80
104
|
default: "",
|
|
81
105
|
envVar: "MINK_SYNC_LAST_PULL",
|
|
82
106
|
description: "ISO timestamp of last successful sync pull",
|
|
107
|
+
scope: "local",
|
|
83
108
|
},
|
|
84
109
|
];
|
|
85
110
|
|