opensoul 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.
package/SKILL.md ADDED
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: opensoul
3
+ description: Search, browse, and swap bot personality (SOUL.md) files from the OpenSOUL.md registry
4
+ metadata:
5
+ {
6
+ "openclaw": { "requires": { "bins": ["soul"] }, "primaryEnv": null },
7
+ "install":
8
+ [
9
+ {
10
+ "id": "npm",
11
+ "kind": "node",
12
+ "package": "opensoul",
13
+ "bins": ["soul"],
14
+ "label": "Install via npm",
15
+ },
16
+ ],
17
+ }
18
+ ---
19
+
20
+ You can manage the bot's personality by swapping SOUL.md files from the OpenSoul registry.
21
+
22
+ ## Available actions
23
+
24
+ ### Possess — swap soul
25
+
26
+ When the user asks to change personality/soul:
27
+
28
+ 1. Run `soul possess <name> --yes` — this auto-summons from the registry if the soul isn't cached locally.
29
+
30
+ You can also possess from a local file path: `soul possess /path/to/SOUL.md --yes`
31
+
32
+ Use `--dry-run` to preview what would happen without writing anything.
33
+
34
+ ### Exorcise — restore original
35
+
36
+ If the user wants to go back to their original personality: `soul exorcise`
37
+
38
+ This restores the backed-up SOUL.md from before the first possession.
39
+
40
+ ### Search souls
41
+
42
+ To search the registry: `soul search <query> --no-interactive`
43
+
44
+ Sorting options:
45
+
46
+ - `--top` — sort by highest-rated
47
+ - `--popular` — sort by most downloaded
48
+
49
+ To show all available souls: `soul search --top --no-interactive`
50
+
51
+ ### Summon — download without swapping
52
+
53
+ To download a soul to local cache without activating it: `soul summon <label>`
54
+
55
+ The user can activate it later with `soul possess <name>`.
56
+
57
+ ### List cached souls
58
+
59
+ To show locally cached souls: `soul list`
60
+
61
+ Supports pagination with `--page <n>` and `--per-page <n>`.
62
+
63
+ ### Banish — remove from cache
64
+
65
+ To remove a soul from the local cache: `soul banish <name>`
66
+
67
+ ### Status
68
+
69
+ To check what soul is currently loaded: `soul status`
70
+
71
+ Shows the SOUL.md path, swap state (original or swapped), and backup status.
72
+
73
+ ### Path — show or set SOUL.md location
74
+
75
+ To show the current SOUL.md path: `soul path`
76
+
77
+ To set a new path: `soul path /path/to/SOUL.md`
78
+
79
+ To show or set the OpenClaw skills directory: `soul path --skills` or `soul path /path/to/skills --skills`
80
+
81
+ ### Config
82
+
83
+ To get or set CLI configuration values:
84
+
85
+ - `soul config get <key>`
86
+ - `soul config set <key> <value>`
87
+
88
+ ### Install / Uninstall skill
89
+
90
+ To install the OpenSoul skill into OpenClaw: `soul install`
91
+
92
+ To remove it: `soul uninstall`
93
+
94
+ ## Important notes
95
+
96
+ - Always use `--no-interactive` with `soul search` since you cannot use interactive TUI controls.
97
+ - Always use `--yes` with `soul possess` to skip the confirmation prompt.
98
+ - `soul possess` auto-summons from the registry if the soul isn't in the local cache — you don't need to summon first.
99
+ - After possessing a soul, let the user know they can use `soul exorcise` to restore their original personality.
100
+ - The soul takes effect on the next conversation — the current conversation is not affected.
@@ -0,0 +1,18 @@
1
+ interface CacheEntry {
2
+ name: string;
3
+ label?: string;
4
+ file: string;
5
+ hash: string;
6
+ cachedAt: string;
7
+ lastUsedAt?: string;
8
+ }
9
+ export declare function cacheSoul(name: string, content: string, hash: string, label?: string): string;
10
+ export declare function listCached(): CacheEntry[];
11
+ export declare function getCached(query: string): {
12
+ content: string;
13
+ entry: CacheEntry;
14
+ } | null;
15
+ export declare function touchCached(query: string): void;
16
+ export declare function removeCached(query: string): boolean;
17
+ export {};
18
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CA4B7F;AAED,wBAAgB,UAAU,IAAI,UAAU,EAAE,CAEzC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAStF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAO/C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAcnD"}
package/dist/cache.js ADDED
@@ -0,0 +1,86 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ function getCacheDir() {
5
+ return join(homedir(), ".soul", "cache");
6
+ }
7
+ function indexPath() {
8
+ return join(getCacheDir(), "index.json");
9
+ }
10
+ function loadIndex() {
11
+ const path = indexPath();
12
+ if (!existsSync(path)) {
13
+ return { entries: [] };
14
+ }
15
+ return JSON.parse(readFileSync(path, "utf-8"));
16
+ }
17
+ function saveIndex(index) {
18
+ const dir = getCacheDir();
19
+ mkdirSync(dir, { recursive: true });
20
+ writeFileSync(indexPath(), JSON.stringify(index, null, 2), "utf-8");
21
+ }
22
+ function matchesEntry(entry, query) {
23
+ const q = query.toLowerCase();
24
+ return (entry.name.toLowerCase() === q ||
25
+ (entry.label != null && entry.label.toLowerCase() === q));
26
+ }
27
+ export function cacheSoul(name, content, hash, label) {
28
+ const dir = getCacheDir();
29
+ mkdirSync(dir, { recursive: true });
30
+ const filename = `${(label ?? name).toLowerCase().replace(/\s+/g, "-")}.soul.md`;
31
+ const filePath = join(dir, filename);
32
+ writeFileSync(filePath, content, "utf-8");
33
+ const index = loadIndex();
34
+ const existing = index.entries.findIndex((e) => e.name === name || (label != null && e.label === label));
35
+ const entry = {
36
+ name,
37
+ label,
38
+ file: filename,
39
+ hash,
40
+ cachedAt: new Date().toISOString(),
41
+ };
42
+ if (existing >= 0) {
43
+ index.entries[existing] = entry;
44
+ }
45
+ else {
46
+ index.entries.push(entry);
47
+ }
48
+ saveIndex(index);
49
+ return filePath;
50
+ }
51
+ export function listCached() {
52
+ return loadIndex().entries;
53
+ }
54
+ export function getCached(query) {
55
+ const index = loadIndex();
56
+ const entry = index.entries.find((e) => matchesEntry(e, query));
57
+ if (!entry)
58
+ return null;
59
+ const filePath = join(getCacheDir(), entry.file);
60
+ if (!existsSync(filePath))
61
+ return null;
62
+ return { content: readFileSync(filePath, "utf-8"), entry };
63
+ }
64
+ export function touchCached(query) {
65
+ const index = loadIndex();
66
+ const entry = index.entries.find((e) => matchesEntry(e, query));
67
+ if (entry) {
68
+ entry.lastUsedAt = new Date().toISOString();
69
+ saveIndex(index);
70
+ }
71
+ }
72
+ export function removeCached(query) {
73
+ const index = loadIndex();
74
+ const idx = index.entries.findIndex((e) => matchesEntry(e, query));
75
+ if (idx === -1)
76
+ return false;
77
+ const entry = index.entries[idx];
78
+ const filePath = join(getCacheDir(), entry.file);
79
+ if (existsSync(filePath)) {
80
+ rmSync(filePath);
81
+ }
82
+ index.entries.splice(idx, 1);
83
+ saveIndex(index);
84
+ return true;
85
+ }
86
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface SoulConfig {
2
+ registry_url: string;
3
+ soul_path: string;
4
+ skills_path: string;
5
+ }
6
+ export declare function loadConfig(): SoulConfig;
7
+ export declare function saveConfig(config: SoulConfig): void;
8
+ export declare function getConfigValue(key: string): string | undefined;
9
+ export declare function setConfigValue(key: string, value: string): void;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAcD,wBAAgB,UAAU,IAAI,UAAU,CAUvC;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGnD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI9D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAK/D"}
package/dist/config.js ADDED
@@ -0,0 +1,41 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { parse, stringify } from "yaml";
5
+ function defaultConfig() {
6
+ return {
7
+ registry_url: "https://opensoul-api.zyliu-daniel.workers.dev",
8
+ soul_path: join(homedir(), ".openclaw", "workspace", "SOUL.md"),
9
+ skills_path: join(homedir(), ".openclaw", "skills"),
10
+ };
11
+ }
12
+ function configPath() {
13
+ return join(homedir(), ".soulrc.yaml");
14
+ }
15
+ export function loadConfig() {
16
+ const path = configPath();
17
+ const defaults = defaultConfig();
18
+ if (!existsSync(path)) {
19
+ saveConfig(defaults);
20
+ return { ...defaults };
21
+ }
22
+ const raw = readFileSync(path, "utf-8");
23
+ const parsed = parse(raw);
24
+ return { ...defaults, ...parsed };
25
+ }
26
+ export function saveConfig(config) {
27
+ const path = configPath();
28
+ writeFileSync(path, stringify(config), "utf-8");
29
+ }
30
+ export function getConfigValue(key) {
31
+ const config = loadConfig();
32
+ const record = config;
33
+ return record[key];
34
+ }
35
+ export function setConfigValue(key, value) {
36
+ const config = loadConfig();
37
+ const record = config;
38
+ record[key] = value;
39
+ saveConfig(config);
40
+ }
41
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAa,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAQxC,SAAS,aAAa;IACpB,OAAO;QACL,YAAY,EAAE,+CAA+C;QAC7D,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC;QAC/D,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,UAAU,CAAC,QAAQ,CAAC,CAAC;QACrB,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAwB,CAAC;IACjD,OAAO,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAkB;IAC3C,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAA4C,CAAC;IAC5D,OAAO,MAAM,CAAC,GAAG,CAAuB,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,KAAa;IACvD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,MAA2C,CAAC;IAC3D,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACpB,UAAU,CAAC,MAAM,CAAC,CAAC;AACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,471 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync, existsSync } from "node:fs";
4
+ import { resolve, dirname, basename } from "node:path";
5
+ import { createInterface } from "node:readline";
6
+ import pc from "picocolors";
7
+ import { createHash } from "node:crypto";
8
+ import { loadConfig, getConfigValue, setConfigValue } from "./config.js";
9
+ import { listCached, getCached, cacheSoul, removeCached, touchCached, } from "./cache.js";
10
+ import { swapSoul, rollbackSoul, hasBackup, isSwapped, readCurrentSoul, getSoulPath, } from "./swap.js";
11
+ import { RegistryClient } from "./registry-client.js";
12
+ import { installSkill, uninstallSkill, isSkillInstalled, } from "./skill.js";
13
+ import { fileURLToPath } from "node:url";
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
16
+ let verbose = false;
17
+ function log(...args) {
18
+ if (verbose)
19
+ console.error(pc.dim("[verbose]"), ...args);
20
+ }
21
+ function fail(message) {
22
+ console.error(pc.red(message));
23
+ process.exit(1);
24
+ }
25
+ const SPINNER_FRAMES = ["◐", "◓", "◑", "◒"];
26
+ function spinner(message) {
27
+ let i = 0;
28
+ const stream = process.stderr;
29
+ stream.write(` ${SPINNER_FRAMES[0]} ${message}`);
30
+ const timer = setInterval(() => {
31
+ i = (i + 1) % SPINNER_FRAMES.length;
32
+ stream.write(`\r ${SPINNER_FRAMES[i]} ${message}`);
33
+ }, 100);
34
+ return {
35
+ stop(finalMessage) {
36
+ clearInterval(timer);
37
+ stream.write(`\r${" ".repeat(message.length + 10)}\r`);
38
+ if (finalMessage)
39
+ console.log(finalMessage);
40
+ },
41
+ };
42
+ }
43
+ function confirm(prompt, defaultYes = false) {
44
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
45
+ const hint = defaultYes ? "[Y/n]" : "[y/N]";
46
+ return new Promise((resolve) => {
47
+ rl.question(`${prompt} ${hint} `, (answer) => {
48
+ rl.close();
49
+ const trimmed = answer.trim().toLowerCase();
50
+ if (trimmed === "")
51
+ resolve(defaultYes);
52
+ else
53
+ resolve(trimmed === "y");
54
+ });
55
+ });
56
+ }
57
+ const program = new Command();
58
+ program
59
+ .name("soul")
60
+ .description("OpenSoul CLI — manage swappable bot personality files")
61
+ .version(pkg.version, "-v, --version")
62
+ .option("--verbose", "Enable verbose output for debugging")
63
+ .hook("preAction", () => {
64
+ verbose = program.opts().verbose ?? false;
65
+ });
66
+ // --- possess ---
67
+ program
68
+ .command("possess <pathOrName>")
69
+ .description("Swap your bot's SOUL.md with a soul file or cached soul")
70
+ .option("--dry-run", "Preview the swap without writing anything")
71
+ .option("-y, --yes", "Skip confirmation prompt")
72
+ .action(async (pathOrName, opts) => {
73
+ let content;
74
+ let source;
75
+ let soulName;
76
+ const filePath = resolve(pathOrName);
77
+ if (existsSync(filePath)) {
78
+ content = readFileSync(filePath, "utf-8");
79
+ source = filePath;
80
+ log(`Reading from file: ${filePath}`);
81
+ }
82
+ else {
83
+ const cached = getCached(pathOrName);
84
+ if (cached) {
85
+ content = cached.content;
86
+ source = `cache:${cached.entry.name}`;
87
+ soulName = cached.entry.name;
88
+ log(`Reading from cache: ${cached.entry.name}`);
89
+ }
90
+ else {
91
+ // Check cache for fuzzy matches before hitting the network
92
+ const normalize = (s) => s
93
+ .toLowerCase()
94
+ .replace(/[-_\s]+/g, " ")
95
+ .trim();
96
+ const input = normalize(pathOrName);
97
+ const allCached = listCached();
98
+ const fuzzyMatches = allCached.filter((e) => {
99
+ const n = normalize(e.name);
100
+ return n.includes(input) || input.includes(n);
101
+ });
102
+ if (fuzzyMatches.length > 0) {
103
+ const labels = fuzzyMatches.map((e) => pc.cyan(e.name));
104
+ fail(`Soul '${pathOrName}' not found in cache.\n\n Did you mean one of these?\n${labels.map((l) => ` ${l}`).join("\n")}\n\n Use the exact name, or 'soul summon <label>' to download from the registry.`);
105
+ }
106
+ // Auto-summon from registry — normalize to label format (spaces → hyphens, lowercase)
107
+ const label = pathOrName.trim().toLowerCase().replace(/\s+/g, "-");
108
+ const s = spinner(pc.cyan("🔮 Summoning soul from registry..."));
109
+ try {
110
+ const client = new RegistryClient();
111
+ log(`Registry URL: ${loadConfig().registry_url}`);
112
+ log(`Trying label: ${label}`);
113
+ const [meta, fetchedContent] = await Promise.all([
114
+ client.getMeta(label),
115
+ client.getContent(label),
116
+ ]);
117
+ content = fetchedContent;
118
+ const hash = createHash("sha256").update(content).digest("hex");
119
+ const name = meta.name;
120
+ cacheSoul(name, content, hash, meta.label);
121
+ soulName = name;
122
+ source = `registry:${meta.label}`;
123
+ s.stop(pc.green(`🔮 Summoned ${pc.yellow(pc.bold(name))} (${meta.label})`));
124
+ }
125
+ catch (err) {
126
+ s.stop();
127
+ // Try to suggest similar souls from the registry — search by first word for broader matches
128
+ let suggestion = "";
129
+ try {
130
+ const words = pathOrName
131
+ .replace(/[-_]/g, " ")
132
+ .trim()
133
+ .split(/\s+/);
134
+ const searchTerm = words[0];
135
+ const client = new RegistryClient();
136
+ const { data: results } = await client.search(searchTerm, undefined, undefined, 5);
137
+ if (results.length > 0) {
138
+ const labels = results.map((r) => pc.cyan(r.label));
139
+ suggestion = `\n\n Did you mean one of these?\n${labels.map((l) => ` ${l}`).join("\n")}`;
140
+ }
141
+ }
142
+ catch {
143
+ // Search failed too — just show the original error
144
+ }
145
+ fail(`Soul '${pathOrName}' not found as a local file, in cache, or in the registry.${suggestion}`);
146
+ }
147
+ }
148
+ }
149
+ const filename = pathOrName.split("/").pop() ?? pathOrName;
150
+ // Validate the target soul path before attempting the swap
151
+ const targetPath = getSoulPath();
152
+ const targetDir = dirname(targetPath);
153
+ if (!existsSync(targetDir)) {
154
+ fail(`Target directory not found: ${pc.yellow(targetDir)}\n\n Your configured SOUL.md path is: ${pc.cyan(targetPath)}\n Use ${pc.bold("soul path <newPath>")} to set the correct path to your SOUL.md file.`);
155
+ }
156
+ if (basename(targetPath) !== "SOUL.md") {
157
+ fail(`Configured path points to ${pc.yellow(basename(targetPath))}, expected ${pc.cyan("SOUL.md")}\n\n Your configured path is: ${pc.cyan(targetPath)}\n Use ${pc.bold("soul path <newPath>")} to set it to a valid SOUL.md file or its parent directory.`);
158
+ }
159
+ if (opts.dryRun) {
160
+ console.log(pc.bold("\n[dry-run] Would possess with:"));
161
+ console.log(` Source: ${source}`);
162
+ console.log(` Target: ${getSoulPath()}`);
163
+ console.log(` Backup: ${!isSwapped() && existsSync(getSoulPath()) ? "would create" : "already exists"}`);
164
+ const preview = content.trim().split("\n")[0] ?? "";
165
+ console.log(` Preview: ${pc.cyan(preview)}`);
166
+ return;
167
+ }
168
+ // Confirmation prompt on first swap (unless --yes or non-interactive)
169
+ if (!opts.yes &&
170
+ !isSwapped() &&
171
+ existsSync(getSoulPath()) &&
172
+ process.stdin.isTTY) {
173
+ console.log(pc.dim(` SOUL.md location: ${getSoulPath()}`));
174
+ const ok = await confirm("This will modify your SOUL.md (original will be backed up locally). Continue?", true);
175
+ if (!ok) {
176
+ console.log(pc.dim("Aborted."));
177
+ return;
178
+ }
179
+ }
180
+ const s = spinner(pc.cyan("👻 Possessing..."));
181
+ const { backedUp } = swapSoul(content);
182
+ if (soulName)
183
+ touchCached(soulName);
184
+ s.stop(pc.green(`\n👻 Possessed with ${pc.yellow(pc.bold(filename))}`));
185
+ console.log(pc.dim(` Written to ${getSoulPath()}`));
186
+ if (backedUp) {
187
+ console.log(pc.dim(` Original SOUL.md backed up (use 'soul exorcise' to restore)`));
188
+ }
189
+ });
190
+ // --- exorcise ---
191
+ program
192
+ .command("exorcise")
193
+ .description("Restore the original SOUL.md from backup")
194
+ .action(() => {
195
+ if (!hasBackup()) {
196
+ fail("No backup found. Nothing to exorcise.");
197
+ }
198
+ const restored = rollbackSoul();
199
+ if (restored) {
200
+ console.log(pc.green(`\n🕯️ Soul exorcised — ${pc.yellow("SOUL.md")} restored`));
201
+ console.log(pc.dim(` ${getSoulPath()}`));
202
+ }
203
+ else {
204
+ fail("Failed to exorcise soul.");
205
+ }
206
+ });
207
+ // --- search ---
208
+ program
209
+ .command("search [query]")
210
+ .description("Search the soul registry")
211
+ .option("--top", "Sort by highest-rated")
212
+ .option("--popular", "Sort by most popular")
213
+ .option("--no-interactive", "Print results without interactive selection")
214
+ .action(async (query, opts) => {
215
+ try {
216
+ const client = new RegistryClient();
217
+ const sort = opts.top ? "top" : opts.popular ? "popular" : undefined;
218
+ log(`Searching registry: query=${query ?? "(all)"} sort=${sort ?? "recent"}`);
219
+ const { data: results, pagination } = await client.search(query, sort);
220
+ if (results.length === 0) {
221
+ console.log(pc.yellow("No souls found."));
222
+ return;
223
+ }
224
+ // Non-interactive mode: just print results
225
+ if (!process.stdin.isTTY || opts.interactive === false) {
226
+ console.log(pc.bold(`\n${pagination.total} soul(s) found (page ${pagination.page}/${pagination.totalPages}):\n`));
227
+ for (const soul of results) {
228
+ const rating = soul.rating_avg
229
+ ? pc.yellow(` ★ ${soul.rating_avg.toFixed(1)}`) +
230
+ pc.dim(` (${soul.rating_count} ratings)`)
231
+ : "";
232
+ const desc = soul.description
233
+ ? pc.dim(` — ${soul.description}`)
234
+ : "";
235
+ const nameTag = soul.name !== soul.label ? ` ${pc.yellow(`(${soul.name})`)}` : "";
236
+ console.log(` ${pc.cyan(pc.bold(soul.label))}${nameTag} ${pc.magenta(`by ${soul.author}`)}${rating}${desc}`);
237
+ }
238
+ return;
239
+ }
240
+ // Interactive mode: let user pick a soul
241
+ const { select, confirm: inquirerConfirm } = await import("@inquirer/prompts");
242
+ const choices = results.map((soul) => {
243
+ const rating = soul.rating_avg
244
+ ? pc.yellow(` ★ ${soul.rating_avg.toFixed(1)}`) +
245
+ pc.dim(` (${soul.rating_count})`)
246
+ : "";
247
+ const author = pc.magenta(`by ${soul.author}`);
248
+ const desc = soul.description ? pc.dim(` — ${soul.description}`) : "";
249
+ const nameTag = soul.name !== soul.label ? ` ${pc.yellow(`(${soul.name})`)}` : "";
250
+ return {
251
+ name: `${pc.cyan(pc.bold(soul.label))}${nameTag} ${author}${rating}${desc}`,
252
+ value: soul.label,
253
+ };
254
+ });
255
+ console.log(pc.bold(`\n${pagination.total} soul(s) found:\n`));
256
+ const label = await select({
257
+ message: "Select a soul to pull",
258
+ choices: [
259
+ ...choices,
260
+ { name: pc.dim("Cancel"), value: "__cancel__" },
261
+ ],
262
+ });
263
+ if (label === "__cancel__") {
264
+ return;
265
+ }
266
+ // Summon the selected soul
267
+ log(`Summoning soul '${label}' from registry`);
268
+ const [meta, content] = await Promise.all([
269
+ client.getMeta(label),
270
+ client.getContent(label),
271
+ ]);
272
+ const hash = createHash("sha256").update(content).digest("hex");
273
+ const name = meta.name;
274
+ cacheSoul(name, content, hash, meta.label);
275
+ console.log(pc.green(`🔮 Summoned ${pc.yellow(pc.bold(name))} (${label})`));
276
+ // Ask if they want to possess immediately
277
+ const shouldSwap = await inquirerConfirm({
278
+ message: "Possess your bot with this soul now?",
279
+ default: true,
280
+ });
281
+ if (shouldSwap) {
282
+ const { backedUp } = swapSoul(content);
283
+ console.log(pc.green(`\n👻 Possessed with ${pc.yellow(pc.bold(name))}`));
284
+ console.log(pc.dim(` Written to ${getSoulPath()}`));
285
+ if (backedUp) {
286
+ console.log(pc.dim(` Original SOUL.md backed up (use 'soul exorcise' to restore)`));
287
+ }
288
+ }
289
+ else {
290
+ console.log(pc.dim(` Use 'soul possess ${name}' to activate later.`));
291
+ }
292
+ }
293
+ catch (err) {
294
+ if (err.name === "ExitPromptError") {
295
+ // User pressed Ctrl+C during prompt
296
+ return;
297
+ }
298
+ fail(err.message);
299
+ }
300
+ });
301
+ // --- summon ---
302
+ program
303
+ .command("summon <label>")
304
+ .description("Download a soul from the registry to local cache")
305
+ .action(async (label) => {
306
+ log(`Summoning soul '${label}' from registry`);
307
+ try {
308
+ const client = new RegistryClient();
309
+ log(`Registry URL: ${loadConfig().registry_url}`);
310
+ const [meta, content] = await Promise.all([
311
+ client.getMeta(label),
312
+ client.getContent(label),
313
+ ]);
314
+ const hash = createHash("sha256").update(content).digest("hex");
315
+ const name = meta.name;
316
+ cacheSoul(name, content, hash, meta.label);
317
+ console.log(pc.green(`\n🔮 Summoned ${pc.yellow(pc.bold(name))} (${label})`));
318
+ console.log(pc.dim(` Cached locally. Use 'soul possess ${name}' to activate.`));
319
+ }
320
+ catch (err) {
321
+ fail(err.message);
322
+ }
323
+ });
324
+ // --- list ---
325
+ program
326
+ .command("list")
327
+ .description("List locally cached souls (most recently used first)")
328
+ .option("-p, --page <number>", "Page number", "1")
329
+ .option("-n, --per-page <number>", "Souls per page", "20")
330
+ .action((opts) => {
331
+ const cached = listCached();
332
+ if (cached.length === 0) {
333
+ console.log(pc.yellow("No cached souls. Use 'soul summon <label>' to download one."));
334
+ return;
335
+ }
336
+ const sorted = [...cached].sort((a, b) => {
337
+ const aUsed = a.lastUsedAt ?? "";
338
+ const bUsed = b.lastUsedAt ?? "";
339
+ if (aUsed !== bUsed)
340
+ return bUsed.localeCompare(aUsed);
341
+ return (b.cachedAt ?? "").localeCompare(a.cachedAt ?? "");
342
+ });
343
+ const perPage = Math.max(1, parseInt(opts.perPage, 10) || 20);
344
+ const totalPages = Math.ceil(sorted.length / perPage);
345
+ const page = Math.min(Math.max(1, parseInt(opts.page, 10) || 1), totalPages);
346
+ const start = (page - 1) * perPage;
347
+ const pageItems = sorted.slice(start, start + perPage);
348
+ for (const entry of pageItems) {
349
+ const label = entry.label ?? entry.name.toLowerCase().replace(/\s+/g, "-");
350
+ const nameDisplay = entry.label && entry.name !== entry.label
351
+ ? ` ${pc.dim(`(${entry.name})`)}`
352
+ : "";
353
+ console.log(` ${pc.yellow(label)}${nameDisplay}`);
354
+ }
355
+ if (totalPages > 1) {
356
+ console.log(pc.dim(`\n Page ${page}/${totalPages} (${sorted.length} souls)`));
357
+ }
358
+ });
359
+ // --- banish ---
360
+ program
361
+ .command("banish <name>")
362
+ .description("Remove a soul from the local cache")
363
+ .action((name) => {
364
+ const removed = removeCached(name);
365
+ if (removed) {
366
+ console.log(pc.green(`\n🚪 Banished ${pc.yellow(pc.bold(name))} from cache`));
367
+ }
368
+ else {
369
+ fail(`Soul '${name}' not found in cache.`);
370
+ }
371
+ });
372
+ // --- status ---
373
+ program
374
+ .command("status")
375
+ .description("Show current SOUL.md status and swap state")
376
+ .action(() => {
377
+ const soulPath = getSoulPath();
378
+ const wsDir = dirname(soulPath);
379
+ if (!existsSync(wsDir)) {
380
+ console.log(pc.yellow(`OpenClaw workspace not found at ${wsDir}`));
381
+ console.log(pc.dim("Is OpenClaw installed? Expected ~/.openclaw/workspace/"));
382
+ return;
383
+ }
384
+ const content = readCurrentSoul();
385
+ if (!content) {
386
+ console.log(pc.yellow(`No SOUL.md found at ${soulPath}`));
387
+ return;
388
+ }
389
+ const swapped = isSwapped();
390
+ console.log(pc.bold("\nSOUL.md Status"));
391
+ console.log(`Path: ${soulPath}`);
392
+ console.log(`State: ${swapped ? pc.cyan("swapped") : pc.green("original")}`);
393
+ console.log(`Backup: ${hasBackup() ? pc.green("saved") : pc.dim("none")}`);
394
+ if (swapped) {
395
+ const rawContent = content.split("\n").slice(1).join("\n");
396
+ const firstLine = rawContent.trim().split("\n")[0] ?? "";
397
+ console.log(`Preview: ${pc.cyan(firstLine)}`);
398
+ }
399
+ });
400
+ // --- path ---
401
+ program
402
+ .command("path [newPath]")
403
+ .description("Show or set the SOUL.md file path (or --skills for skills dir)")
404
+ .option("--skills", "Show or set the OpenClaw skills directory path")
405
+ .action((newPath, opts) => {
406
+ const key = opts.skills ? "skills_path" : "soul_path";
407
+ const label = opts.skills ? "Skills path" : "SOUL.md path";
408
+ if (newPath) {
409
+ const resolved = resolve(newPath);
410
+ setConfigValue(key, resolved);
411
+ console.log(pc.green(` ${label} set to ${pc.yellow(resolved)}`));
412
+ }
413
+ else {
414
+ console.log(opts.skills ? loadConfig().skills_path : getSoulPath());
415
+ }
416
+ });
417
+ // --- install ---
418
+ program
419
+ .command("install")
420
+ .description("Install the OpenSoul skill into OpenClaw")
421
+ .action(() => {
422
+ const { path, updated } = installSkill();
423
+ if (updated) {
424
+ console.log(pc.green(`\n✓ Updated OpenSOUL skill`));
425
+ }
426
+ else {
427
+ console.log(pc.green(`\n✓ Installed OpenSOUL skill`));
428
+ }
429
+ console.log(pc.dim(` ${path}`));
430
+ console.log(pc.dim(` Your OpenClaw bot can now swap souls via natural language.`));
431
+ });
432
+ // --- uninstall ---
433
+ program
434
+ .command("uninstall")
435
+ .description("Remove the OpenSoul skill from OpenClaw")
436
+ .action(() => {
437
+ if (!isSkillInstalled()) {
438
+ console.log(pc.yellow("OpenSoul skill is not installed."));
439
+ return;
440
+ }
441
+ const removed = uninstallSkill();
442
+ if (removed) {
443
+ console.log(pc.green("\n✓ Uninstalled OpenSOUL skill"));
444
+ }
445
+ else {
446
+ fail("Failed to uninstall skill.");
447
+ }
448
+ });
449
+ // --- config ---
450
+ const configCmd = program
451
+ .command("config")
452
+ .description("Get or set CLI configuration values");
453
+ configCmd
454
+ .command("get <key>")
455
+ .description("Get a config value")
456
+ .action((key) => {
457
+ const value = getConfigValue(key);
458
+ if (value === undefined) {
459
+ fail(`Unknown config key: ${key}`);
460
+ }
461
+ console.log(value);
462
+ });
463
+ configCmd
464
+ .command("set <key> <value>")
465
+ .description("Set a config value")
466
+ .action((key, value) => {
467
+ setConfigValue(key, value);
468
+ console.log(pc.green(`Set ${key} = ${value}`));
469
+ });
470
+ program.parse();
471
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface RegistrySoul {
2
+ slug: string;
3
+ label: string;
4
+ name: string;
5
+ author: string;
6
+ description: string | null;
7
+ tags: string[];
8
+ rating_avg?: number;
9
+ rating_count?: number;
10
+ created_at: string;
11
+ updated_at: string;
12
+ }
13
+ export declare class RegistryClient {
14
+ private baseUrl;
15
+ constructor(baseUrl?: string);
16
+ search(query?: string, sort?: string, page?: number, limit?: number): Promise<{
17
+ data: RegistrySoul[];
18
+ pagination: {
19
+ page: number;
20
+ limit: number;
21
+ total: number;
22
+ totalPages: number;
23
+ };
24
+ }>;
25
+ getMeta(id: string): Promise<RegistrySoul>;
26
+ getContent(id: string): Promise<string>;
27
+ }
28
+ //# sourceMappingURL=registry-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-client.d.ts","sourceRoot":"","sources":["../src/registry-client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,CAAC,EAAE,MAAM;IAItB,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,YAAY,EAAE,CAAC;QAAC,UAAU,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAqBvL,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAiB1C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgB9C"}
@@ -0,0 +1,54 @@
1
+ import { loadConfig } from "./config.js";
2
+ export class RegistryClient {
3
+ baseUrl;
4
+ constructor(baseUrl) {
5
+ this.baseUrl = baseUrl ?? loadConfig().registry_url;
6
+ }
7
+ async search(query, sort, page, limit) {
8
+ const params = new URLSearchParams();
9
+ if (query)
10
+ params.set("search", query);
11
+ if (sort)
12
+ params.set("sort", sort);
13
+ if (page)
14
+ params.set("page", String(page));
15
+ if (limit)
16
+ params.set("limit", String(limit));
17
+ const qs = params.toString();
18
+ const url = `${this.baseUrl}/api/v1/souls${qs ? `?${qs}` : ""}`;
19
+ const res = await fetch(url).catch(() => {
20
+ throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
21
+ });
22
+ if (!res.ok) {
23
+ throw new Error(`Registry returned HTTP ${res.status}`);
24
+ }
25
+ return res.json();
26
+ }
27
+ async getMeta(id) {
28
+ const url = `${this.baseUrl}/api/v1/souls/${id}`;
29
+ const res = await fetch(url).catch(() => {
30
+ throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
31
+ });
32
+ if (!res.ok) {
33
+ if (res.status === 404) {
34
+ throw new Error(`Soul '${id}' not found in registry`);
35
+ }
36
+ throw new Error(`Registry returned HTTP ${res.status}`);
37
+ }
38
+ return res.json();
39
+ }
40
+ async getContent(id) {
41
+ const url = `${this.baseUrl}/api/v1/souls/${id}/content`;
42
+ const res = await fetch(url).catch(() => {
43
+ throw new Error(`Failed to connect to registry at ${this.baseUrl}. Is it reachable?`);
44
+ });
45
+ if (!res.ok) {
46
+ if (res.status === 404) {
47
+ throw new Error(`Soul '${id}' not found in registry`);
48
+ }
49
+ throw new Error(`Registry returned HTTP ${res.status}`);
50
+ }
51
+ return res.text();
52
+ }
53
+ }
54
+ //# sourceMappingURL=registry-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-client.js","sourceRoot":"","sources":["../src/registry-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function isSkillInstalled(): boolean;
2
+ export declare function getSkillPath(): string;
3
+ export declare function installSkill(): {
4
+ path: string;
5
+ updated: boolean;
6
+ };
7
+ export declare function uninstallSkill(): boolean;
8
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAiCA,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CASjE;AAED,wBAAgB,cAAc,IAAI,OAAO,CAKxC"}
package/dist/skill.js ADDED
@@ -0,0 +1,41 @@
1
+ import { writeFileSync, readFileSync, mkdirSync, existsSync, rmSync, } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { loadConfig } from "./config.js";
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const SKILL_DIR_NAME = "opensoul";
7
+ function skillsDir() {
8
+ return loadConfig().skills_path;
9
+ }
10
+ function skillDir() {
11
+ return join(skillsDir(), SKILL_DIR_NAME);
12
+ }
13
+ function skillPath() {
14
+ return join(skillDir(), "SKILL.md");
15
+ }
16
+ function loadSkillContent() {
17
+ // SKILL.md is bundled at the package root (sibling to dist/)
18
+ const path = join(__dirname, "..", "SKILL.md");
19
+ return readFileSync(path, "utf-8");
20
+ }
21
+ export function isSkillInstalled() {
22
+ return existsSync(skillPath());
23
+ }
24
+ export function getSkillPath() {
25
+ return skillPath();
26
+ }
27
+ export function installSkill() {
28
+ const dir = skillDir();
29
+ const path = skillPath();
30
+ const updated = existsSync(path);
31
+ mkdirSync(dir, { recursive: true });
32
+ writeFileSync(path, loadSkillContent(), "utf-8");
33
+ return { path, updated };
34
+ }
35
+ export function uninstallSkill() {
36
+ if (!existsSync(skillPath()))
37
+ return false;
38
+ rmSync(skillDir(), { recursive: true });
39
+ return true;
40
+ }
41
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,YAAY,EACZ,SAAS,EACT,UAAU,EACV,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC,SAAS,SAAS;IAChB,OAAO,UAAU,EAAE,CAAC,WAAW,CAAC;AAClC,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,cAAc,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,QAAQ,EAAE,EAAE,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,gBAAgB;IACvB,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAEjC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,aAAa,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,OAAO,CAAC,CAAC;IAEjD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE3C,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC"}
package/dist/swap.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare function getSoulPath(): string;
2
+ export declare function isSwapped(): boolean;
3
+ export declare function readCurrentSoul(): string | null;
4
+ export declare function hasBackup(): boolean;
5
+ export declare function swapSoul(newContent: string): {
6
+ backedUp: boolean;
7
+ };
8
+ export declare function rollbackSoul(): boolean;
9
+ //# sourceMappingURL=swap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../src/swap.ts"],"names":[],"mappings":"AAuBA,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,SAAS,IAAI,OAAO,CAKnC;AAED,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAI/C;AAED,wBAAgB,SAAS,IAAI,OAAO,CAEnC;AAED,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAiBlE;AAED,wBAAgB,YAAY,IAAI,OAAO,CAKtC"}
package/dist/swap.js ADDED
@@ -0,0 +1,59 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync, statSync } from "node:fs";
2
+ import { join, dirname } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { loadConfig } from "./config.js";
5
+ const SWAP_MARKER = "<!-- opensoul:swapped -->";
6
+ function soulPath() {
7
+ const p = loadConfig().soul_path;
8
+ if (existsSync(p) && statSync(p).isDirectory()) {
9
+ return join(p, "SOUL.md");
10
+ }
11
+ return p;
12
+ }
13
+ function backupDir() {
14
+ return join(homedir(), ".soul", "backup");
15
+ }
16
+ function backupPath() {
17
+ return join(backupDir(), "SOUL.md.original");
18
+ }
19
+ export function getSoulPath() {
20
+ return soulPath();
21
+ }
22
+ export function isSwapped() {
23
+ const p = soulPath();
24
+ if (!existsSync(p))
25
+ return false;
26
+ const content = readFileSync(p, "utf-8");
27
+ return content.startsWith(SWAP_MARKER);
28
+ }
29
+ export function readCurrentSoul() {
30
+ const p = soulPath();
31
+ if (!existsSync(p))
32
+ return null;
33
+ return readFileSync(p, "utf-8");
34
+ }
35
+ export function hasBackup() {
36
+ return existsSync(backupPath());
37
+ }
38
+ export function swapSoul(newContent) {
39
+ let backedUp = false;
40
+ const p = soulPath();
41
+ // If current SOUL.md is NOT already a swapped one, back it up
42
+ if (!isSwapped() && existsSync(p)) {
43
+ mkdirSync(backupDir(), { recursive: true });
44
+ copyFileSync(p, backupPath());
45
+ backedUp = true;
46
+ }
47
+ // Write the new soul with the swap marker
48
+ mkdirSync(dirname(p), { recursive: true });
49
+ const marked = `${SWAP_MARKER}\n${newContent}`;
50
+ writeFileSync(p, marked, "utf-8");
51
+ return { backedUp };
52
+ }
53
+ export function rollbackSoul() {
54
+ if (!existsSync(backupPath()))
55
+ return false;
56
+ copyFileSync(backupPath(), soulPath());
57
+ return true;
58
+ }
59
+ //# sourceMappingURL=swap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.js","sourceRoot":"","sources":["../src/swap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAEhD,SAAS,QAAQ;IACf,MAAM,CAAC,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC;IACjC,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAAkB;IACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IAErB,8DAA8D;IAC9D,IAAI,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,SAAS,CAAC,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,YAAY,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9B,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,0CAA0C;IAC1C,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,GAAG,WAAW,KAAK,UAAU,EAAE,CAAC;IAC/C,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAE5C,YAAY,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "opensoul",
3
+ "version": "0.1.0",
4
+ "description": "Swappable bot personality files — search, pull, and swap SOUL.md files from the Soul.MD registry",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/opensoul/cli"
10
+ },
11
+ "homepage": "https://opensoul.md",
12
+ "keywords": [
13
+ "soul",
14
+ "opensoul",
15
+ "bot",
16
+ "personality",
17
+ "openclaw",
18
+ "ai",
19
+ "llm",
20
+ "swap"
21
+ ],
22
+ "bin": {
23
+ "soul": "./dist/index.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "SKILL.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "test": "vitest run --passWithNoTests",
32
+ "dev": "tsx --watch src/index.ts",
33
+ "prepublishOnly": "pnpm run build"
34
+ },
35
+ "dependencies": {
36
+ "@inquirer/prompts": "^8.2.0",
37
+ "@opensoul/core": "workspace:*",
38
+ "commander": "^13.0.0",
39
+ "picocolors": "^1.1.0",
40
+ "yaml": "^2.7.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^22.0.0",
44
+ "tsx": "^4.19.0",
45
+ "typescript": "^5.7.0",
46
+ "vitest": "^3.0.0"
47
+ }
48
+ }