@clawrise/clawrise-cli 0.1.0-alpha.5 → 0.1.0-alpha.6

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,11 +1,17 @@
1
1
  # @clawrise/clawrise-cli
2
2
 
3
- 通过 npm 分发的 Clawrise CLI 根包。
3
+ Clawrise CLI root package distributed through npm.
4
4
 
5
- 用户安装方式:
5
+ ## Install Globally
6
6
 
7
7
  ```bash
8
8
  npm install -g @clawrise/clawrise-cli
9
9
  ```
10
10
 
11
- 安装后会自动选择当前平台对应的预编译二进制,并携带第一方 `feishu` / `notion` provider plugin。
11
+ ## For AI
12
+
13
+ Send the following prompt to the AI assistant:
14
+
15
+ ```text
16
+ Access https://raw.githubusercontent.com/repothread/clawrise-cli/main/docs/en/ai-install.md and follow the steps there to install the `clawrise` command and run setup for the current client.
17
+ ```
package/bin/clawrise.js CHANGED
@@ -5,6 +5,21 @@
5
5
  const childProcess = require('child_process');
6
6
  const path = require('path');
7
7
  const { resolvePlatformPackage } = require('../lib/platform');
8
+ const { handleSetupCommand } = require('../lib/setup');
9
+
10
+ const rawArgs = process.argv.slice(2);
11
+
12
+ if (rawArgs[0] === 'setup') {
13
+ try {
14
+ const handledExitCode = handleSetupCommand(rawArgs.slice(1));
15
+ if (typeof handledExitCode === 'number') {
16
+ process.exit(handledExitCode);
17
+ }
18
+ } catch (error) {
19
+ console.error(error.message);
20
+ process.exit(1);
21
+ }
22
+ }
8
23
 
9
24
  const platformPackage = resolvePlatformPackage();
10
25
  const pluginPath = path.join(platformPackage.dir, 'plugins');
@@ -14,7 +29,7 @@ nextEnv.CLAWRISE_PLUGIN_PATHS = nextEnv.CLAWRISE_PLUGIN_PATHS
14
29
  ? `${pluginPath}${path.delimiter}${nextEnv.CLAWRISE_PLUGIN_PATHS}`
15
30
  : pluginPath;
16
31
 
17
- const result = childProcess.spawnSync(platformPackage.binaryPath, process.argv.slice(2), {
32
+ const result = childProcess.spawnSync(platformPackage.binaryPath, rawArgs, {
18
33
  stdio: 'inherit',
19
34
  env: nextEnv,
20
35
  });
package/lib/platform.js CHANGED
@@ -1,29 +1,34 @@
1
1
  'use strict';
2
2
 
3
+ const fs = require('fs');
3
4
  const path = require('path');
4
5
 
5
- const packageMap = {
6
- 'darwin:arm64': 'clawrise-cli-darwin-arm64',
7
- 'darwin:x64': 'clawrise-cli-darwin-x64',
8
- 'linux:arm64': 'clawrise-cli-linux-arm64',
9
- 'linux:x64': 'clawrise-cli-linux-x64',
10
- 'win32:arm64': 'clawrise-cli-win32-arm64',
11
- 'win32:x64': 'clawrise-cli-win32-x64',
6
+ const platformSuffixMap = {
7
+ 'darwin:arm64': 'darwin-arm64',
8
+ 'darwin:x64': 'darwin-x64',
9
+ 'linux:arm64': 'linux-arm64',
10
+ 'linux:x64': 'linux-x64',
11
+ 'win32:arm64': 'win32-arm64',
12
+ 'win32:x64': 'win32-x64',
12
13
  };
13
14
 
14
15
  function resolvePlatformPackage() {
15
16
  const platformKey = `${process.platform}:${process.arch}`;
16
- const packageName = packageMap[platformKey];
17
+ const packageSuffix = platformSuffixMap[platformKey];
17
18
 
18
- if (!packageName) {
19
- throw new Error(`当前平台暂不支持: ${process.platform}/${process.arch}`);
19
+ if (!packageSuffix) {
20
+ throw new Error(`The current platform is not supported: ${process.platform}/${process.arch}`);
20
21
  }
21
22
 
23
+ // Keep the platform package under the same scope / prefix as the root package,
24
+ // otherwise scoped releases cannot resolve the installed platform bundle.
25
+ const packageName = appendPackageSuffix(resolveRootPackageName(), packageSuffix);
26
+
22
27
  let packageJSONPath;
23
28
  try {
24
29
  packageJSONPath = require.resolve(`${packageName}/package.json`);
25
30
  } catch (error) {
26
- throw new Error(`未找到当前平台对应的二进制包 ${packageName},请重新执行 npm install clawrise-cli。`);
31
+ throw new Error(`The platform binary package ${packageName} was not found. Re-run npm install for the root package.`);
27
32
  }
28
33
 
29
34
  const packageDir = path.dirname(packageJSONPath);
@@ -36,6 +41,41 @@ function resolvePlatformPackage() {
36
41
  };
37
42
  }
38
43
 
44
+ function resolveRootPackageName() {
45
+ const envName = String(process.env.CLAWRISE_ROOT_PACKAGE_NAME || '').trim();
46
+ if (envName !== '') {
47
+ return envName;
48
+ }
49
+
50
+ const packageJSONPath = path.join(resolvePackageRootDir(), 'package.json');
51
+ if (!fs.existsSync(packageJSONPath)) {
52
+ throw new Error(`The root package metadata was not found: ${packageJSONPath}`);
53
+ }
54
+
55
+ const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf8'));
56
+ const packageName = String(packageJSON.name || '').trim();
57
+ if (packageName === '') {
58
+ throw new Error(`The root package name is missing in ${packageJSONPath}`);
59
+ }
60
+ return packageName;
61
+ }
62
+
63
+ function resolvePackageRootDir() {
64
+ return path.resolve(__dirname, '..');
65
+ }
66
+
67
+ function appendPackageSuffix(packageName, suffix) {
68
+ if (packageName.startsWith('@')) {
69
+ const separatorIndex = packageName.indexOf('/');
70
+ if (separatorIndex > 0 && separatorIndex < packageName.length - 1) {
71
+ const scope = packageName.slice(0, separatorIndex + 1);
72
+ const baseName = packageName.slice(separatorIndex + 1);
73
+ return `${scope}${baseName}-${suffix}`;
74
+ }
75
+ }
76
+ return `${packageName}-${suffix}`;
77
+ }
78
+
39
79
  module.exports = {
40
80
  resolvePlatformPackage,
41
81
  };
package/lib/setup.js ADDED
@@ -0,0 +1,376 @@
1
+ 'use strict';
2
+
3
+ const childProcess = require('child_process');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+
8
+ const supportedClients = ['codex', 'claude-code', 'openclaw', 'opencode'];
9
+ const supportedPlatforms = ['feishu', 'notion'];
10
+ const platformSkillMap = {
11
+ feishu: 'clawrise-feishu',
12
+ notion: 'clawrise-notion',
13
+ };
14
+
15
+ function handleSetupCommand(rawArgs) {
16
+ const parsed = parseSetupArgs(rawArgs);
17
+ ensureValidClient(parsed.client);
18
+ ensureValidPlatforms(parsed.platforms);
19
+ ensureCLICommandInstalled(parsed);
20
+
21
+ const targetRootDir = resolveClientSkillsDir(parsed);
22
+ const selectedSkills = resolveRequestedSkillNames(parsed.platforms);
23
+ const targetName = displayClientName(parsed.client);
24
+
25
+ installBundledSkillsInto(selectedSkills, targetRootDir, targetName);
26
+ return 0;
27
+ }
28
+
29
+ function parseSetupArgs(args) {
30
+ const result = {
31
+ client: '',
32
+ platforms: [],
33
+ codexHome: '',
34
+ claudeHome: '',
35
+ openclawHome: '',
36
+ opencodeConfigHome: '',
37
+ skillsDir: '',
38
+ skipCliInstall: false,
39
+ };
40
+
41
+ for (let index = 0; index < args.length; index += 1) {
42
+ const token = String(args[index] || '').trim();
43
+ if (token === '') {
44
+ continue;
45
+ }
46
+
47
+ if (token === '--codex-home') {
48
+ result.codexHome = readFlagValue(args, index, '--codex-home');
49
+ index += 1;
50
+ continue;
51
+ }
52
+
53
+ if (token === '--claude-home') {
54
+ result.claudeHome = readFlagValue(args, index, '--claude-home');
55
+ index += 1;
56
+ continue;
57
+ }
58
+
59
+ if (token === '--openclaw-home') {
60
+ result.openclawHome = readFlagValue(args, index, '--openclaw-home');
61
+ index += 1;
62
+ continue;
63
+ }
64
+
65
+ if (token === '--opencode-config-home') {
66
+ result.opencodeConfigHome = readFlagValue(args, index, '--opencode-config-home');
67
+ index += 1;
68
+ continue;
69
+ }
70
+
71
+ if (token === '--skills-dir') {
72
+ result.skillsDir = readFlagValue(args, index, '--skills-dir');
73
+ index += 1;
74
+ continue;
75
+ }
76
+
77
+ if (token === '--skip-cli-install') {
78
+ result.skipCliInstall = true;
79
+ continue;
80
+ }
81
+
82
+ if (token === '--help' || token === '-h' || token === 'help') {
83
+ printSetupHelp();
84
+ process.exit(0);
85
+ }
86
+
87
+ if (token.startsWith('-')) {
88
+ throw new Error(`Unsupported argument: ${token}`);
89
+ }
90
+
91
+ if (result.client === '') {
92
+ result.client = token;
93
+ continue;
94
+ }
95
+
96
+ result.platforms.push(token);
97
+ }
98
+
99
+ if (result.client === '') {
100
+ printSetupHelp();
101
+ process.exit(0);
102
+ }
103
+
104
+ return result;
105
+ }
106
+
107
+ function readFlagValue(args, index, flagName) {
108
+ const value = String(args[index + 1] || '').trim();
109
+ if (value === '') {
110
+ throw new Error(`${flagName} requires a directory argument.`);
111
+ }
112
+ return value;
113
+ }
114
+
115
+ function ensureValidClient(client) {
116
+ if (supportedClients.includes(client)) {
117
+ return;
118
+ }
119
+ throw new Error(`Unsupported client: ${client}. Supported clients: ${supportedClients.join(', ')}`);
120
+ }
121
+
122
+ function ensureValidPlatforms(platforms) {
123
+ const invalidPlatforms = platforms.filter((platform) => !supportedPlatforms.includes(platform));
124
+ if (invalidPlatforms.length === 0) {
125
+ return;
126
+ }
127
+ throw new Error(`Unsupported platform: ${invalidPlatforms.join(', ')}. Supported platforms: ${supportedPlatforms.join(', ')}`);
128
+ }
129
+
130
+ function ensureCLICommandInstalled(parsed) {
131
+ if (parsed.skipCliInstall) {
132
+ console.log('Skipping global CLI installation because --skip-cli-install was set.');
133
+ return;
134
+ }
135
+
136
+ if (!shouldInstallCLI()) {
137
+ console.log('The clawrise command is already available. Skipping global CLI installation.');
138
+ return;
139
+ }
140
+
141
+ if (!isCommandAvailable('npm')) {
142
+ throw new Error('npm is required to install the clawrise command globally.');
143
+ }
144
+
145
+ const packageName = resolveCurrentPackageName();
146
+ console.log(`Installing the clawrise command globally from npm package: ${packageName}`);
147
+
148
+ const result = childProcess.spawnSync('npm', ['install', '-g', packageName], {
149
+ stdio: 'inherit',
150
+ });
151
+
152
+ if (result.error) {
153
+ throw result.error;
154
+ }
155
+ if (typeof result.status === 'number' && result.status !== 0) {
156
+ throw new Error(`Global CLI installation failed with exit code ${result.status}.`);
157
+ }
158
+ }
159
+
160
+ function shouldInstallCLI() {
161
+ if (isProbablyNPXInvocation()) {
162
+ return true;
163
+ }
164
+ return !isCommandAvailable('clawrise');
165
+ }
166
+
167
+ function isProbablyNPXInvocation() {
168
+ const executablePath = resolveCurrentExecutablePath();
169
+ return executablePath.includes(`${path.sep}_npx${path.sep}`);
170
+ }
171
+
172
+ function resolveCurrentExecutablePath() {
173
+ const currentPath = process.argv[1] || __filename;
174
+ try {
175
+ return fs.realpathSync(currentPath);
176
+ } catch (error) {
177
+ return path.resolve(currentPath);
178
+ }
179
+ }
180
+
181
+ function isCommandAvailable(commandName) {
182
+ const resolverCommand = process.platform === 'win32' ? 'where' : 'which';
183
+ const result = childProcess.spawnSync(resolverCommand, [commandName], {
184
+ stdio: 'ignore',
185
+ });
186
+ return typeof result.status === 'number' && result.status === 0;
187
+ }
188
+
189
+ function resolveCurrentPackageName() {
190
+ const envName = String(process.env.CLAWRISE_ROOT_PACKAGE_NAME || '').trim();
191
+ if (envName !== '') {
192
+ return envName;
193
+ }
194
+
195
+ const packageJSONPath = path.join(resolvePackageRootDir(), 'package.json');
196
+ if (fs.existsSync(packageJSONPath)) {
197
+ const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf8'));
198
+ if (typeof packageJSON.name === 'string' && packageJSON.name.trim() !== '') {
199
+ return packageJSON.name.trim();
200
+ }
201
+ }
202
+
203
+ return '@clawrise/clawrise-cli';
204
+ }
205
+
206
+ function resolvePackageRootDir() {
207
+ return path.resolve(__dirname, '..');
208
+ }
209
+
210
+ function resolveRequestedSkillNames(platforms) {
211
+ const orderedSkills = ['clawrise-core'];
212
+ for (const platform of platforms) {
213
+ const skillName = platformSkillMap[platform];
214
+ if (skillName && !orderedSkills.includes(skillName)) {
215
+ orderedSkills.push(skillName);
216
+ }
217
+ }
218
+ return orderedSkills;
219
+ }
220
+
221
+ function installBundledSkillsInto(selectedSkills, targetRootDir, targetName) {
222
+ const skillsDir = resolveBundledSkillsDir();
223
+ const packagedSkills = listSkillDirectories(skillsDir);
224
+
225
+ if (packagedSkills.length === 0) {
226
+ throw new Error('No bundled skills were found in the current npm package.');
227
+ }
228
+
229
+ const invalidSkills = selectedSkills.filter((name) => !packagedSkills.includes(name));
230
+ if (invalidSkills.length > 0) {
231
+ throw new Error(`The following skills are not bundled in the current npm package: ${invalidSkills.join(', ')}`);
232
+ }
233
+
234
+ fs.mkdirSync(targetRootDir, { recursive: true });
235
+
236
+ for (const skillName of selectedSkills) {
237
+ const sourceDir = path.join(skillsDir, skillName);
238
+ const targetDir = path.join(targetRootDir, skillName);
239
+ fs.rmSync(targetDir, { recursive: true, force: true });
240
+ copyTree(sourceDir, targetDir);
241
+ console.log(`Installed skill: ${skillName} -> ${targetDir}`);
242
+ }
243
+
244
+ console.log(`Setup completed for ${targetName}. Start a new session or restart the client to load the new skills.`);
245
+ }
246
+
247
+ function resolveBundledSkillsDir() {
248
+ return path.join(resolvePackageRootDir(), 'skills');
249
+ }
250
+
251
+ function resolveClientSkillsDir(parsed) {
252
+ if (String(parsed.skillsDir || '').trim() !== '') {
253
+ return path.resolve(parsed.skillsDir);
254
+ }
255
+
256
+ switch (parsed.client) {
257
+ case 'codex':
258
+ return path.join(resolveCodexHome(parsed.codexHome), 'skills');
259
+ case 'claude-code':
260
+ return path.join(resolveClaudeCodeHome(parsed.claudeHome), 'skills');
261
+ case 'openclaw':
262
+ return path.join(resolveOpenClawHome(parsed.openclawHome), 'skills');
263
+ case 'opencode':
264
+ return path.join(resolveOpenCodeConfigHome(parsed.opencodeConfigHome), 'skills');
265
+ default:
266
+ throw new Error(`Unsupported client: ${parsed.client}`);
267
+ }
268
+ }
269
+
270
+ function displayClientName(client) {
271
+ switch (client) {
272
+ case 'codex':
273
+ return 'Codex';
274
+ case 'claude-code':
275
+ return 'Claude Code';
276
+ case 'openclaw':
277
+ return 'OpenClaw';
278
+ case 'opencode':
279
+ return 'OpenCode';
280
+ default:
281
+ return client;
282
+ }
283
+ }
284
+
285
+ function resolveCodexHome(explicitValue) {
286
+ const value = String(explicitValue || process.env.CODEX_HOME || '').trim();
287
+ if (value !== '') {
288
+ return path.resolve(value);
289
+ }
290
+ return path.join(os.homedir(), '.codex');
291
+ }
292
+
293
+ function resolveClaudeCodeHome(explicitValue) {
294
+ const value = String(explicitValue || process.env.CLAUDE_HOME || '').trim();
295
+ if (value !== '') {
296
+ return path.resolve(value);
297
+ }
298
+ return path.join(os.homedir(), '.claude');
299
+ }
300
+
301
+ function resolveOpenClawHome(explicitValue) {
302
+ const value = String(explicitValue || process.env.OPENCLAW_HOME || '').trim();
303
+ if (value !== '') {
304
+ return path.resolve(value);
305
+ }
306
+ return path.join(os.homedir(), '.openclaw');
307
+ }
308
+
309
+ function resolveOpenCodeConfigHome(explicitValue) {
310
+ const value = String(explicitValue || process.env.OPENCODE_CONFIG_HOME || '').trim();
311
+ if (value !== '') {
312
+ return path.resolve(value);
313
+ }
314
+
315
+ const xdgConfigHome = String(process.env.XDG_CONFIG_HOME || '').trim();
316
+ if (xdgConfigHome !== '') {
317
+ return path.join(path.resolve(xdgConfigHome), 'opencode');
318
+ }
319
+
320
+ return path.join(os.homedir(), '.config', 'opencode');
321
+ }
322
+
323
+ function listSkillDirectories(rootDir) {
324
+ if (!fs.existsSync(rootDir)) {
325
+ return [];
326
+ }
327
+
328
+ return fs.readdirSync(rootDir, { withFileTypes: true })
329
+ .filter((entry) => entry.isDirectory())
330
+ .map((entry) => entry.name)
331
+ .sort();
332
+ }
333
+
334
+ function copyTree(sourceDir, targetDir) {
335
+ const sourceStat = fs.statSync(sourceDir);
336
+ if (!sourceStat.isDirectory()) {
337
+ throw new Error(`Skill source directory does not exist or is not a directory: ${sourceDir}`);
338
+ }
339
+
340
+ fs.mkdirSync(targetDir, { recursive: true });
341
+ for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
342
+ const sourcePath = path.join(sourceDir, entry.name);
343
+ const targetPath = path.join(targetDir, entry.name);
344
+
345
+ if (entry.isDirectory()) {
346
+ copyTree(sourcePath, targetPath);
347
+ continue;
348
+ }
349
+
350
+ if (entry.isSymbolicLink()) {
351
+ const linkTarget = fs.readlinkSync(sourcePath);
352
+ fs.symlinkSync(linkTarget, targetPath);
353
+ continue;
354
+ }
355
+
356
+ fs.copyFileSync(sourcePath, targetPath);
357
+ }
358
+ }
359
+
360
+ function printSetupHelp() {
361
+ console.log('Usage: clawrise setup <client> [platform...]');
362
+ console.log('');
363
+ console.log('Supported clients: codex, claude-code, openclaw, opencode');
364
+ console.log('Supported platforms: feishu, notion');
365
+ console.log('');
366
+ console.log('Examples:');
367
+ console.log(' clawrise setup codex');
368
+ console.log(' clawrise setup codex feishu');
369
+ console.log(' clawrise setup claude-code notion --skills-dir ./.claude/skills');
370
+ console.log(' clawrise setup openclaw feishu --skills-dir ./skills');
371
+ console.log(' clawrise setup opencode notion --skills-dir ./.opencode/skills');
372
+ }
373
+
374
+ module.exports = {
375
+ handleSetupCommand,
376
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clawrise/clawrise-cli",
3
- "version": "0.1.0-alpha.5",
4
- "description": "Clawrise CLI with bundled first-party provider plugins.",
3
+ "version": "0.1.0-alpha.6",
4
+ "description": "Clawrise CLI with bundled first-party provider plugins and setup flows for AI client skills.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -17,14 +17,24 @@
17
17
  "files": [
18
18
  "bin",
19
19
  "lib",
20
+ "skills",
20
21
  "README.md"
21
22
  ],
23
+ "keywords": [
24
+ "clawrise",
25
+ "cli",
26
+ "feishu",
27
+ "notion",
28
+ "codex",
29
+ "skills",
30
+ "setup"
31
+ ],
22
32
  "optionalDependencies": {
23
- "@clawrise/clawrise-cli-darwin-arm64": "0.1.0-alpha.5",
24
- "@clawrise/clawrise-cli-darwin-x64": "0.1.0-alpha.5",
25
- "@clawrise/clawrise-cli-linux-arm64": "0.1.0-alpha.5",
26
- "@clawrise/clawrise-cli-linux-x64": "0.1.0-alpha.5",
27
- "@clawrise/clawrise-cli-win32-arm64": "0.1.0-alpha.5",
28
- "@clawrise/clawrise-cli-win32-x64": "0.1.0-alpha.5"
33
+ "@clawrise/clawrise-cli-darwin-arm64": "0.1.0-alpha.6",
34
+ "@clawrise/clawrise-cli-darwin-x64": "0.1.0-alpha.6",
35
+ "@clawrise/clawrise-cli-linux-arm64": "0.1.0-alpha.6",
36
+ "@clawrise/clawrise-cli-linux-x64": "0.1.0-alpha.6",
37
+ "@clawrise/clawrise-cli-win32-arm64": "0.1.0-alpha.6",
38
+ "@clawrise/clawrise-cli-win32-x64": "0.1.0-alpha.6"
29
39
  }
30
40
  }
@@ -0,0 +1,92 @@
1
+ ---
2
+ name: clawrise-core
3
+ description: Use when a task needs to use the local Clawrise CLI as an execution tool. This includes discovering platforms and operations, checking config and plugin health with doctor, inspecting auth methods, exporting specs, and executing third-party platform operations through `clawrise`. Pair with clawrise-feishu or clawrise-notion for platform-specific work.
4
+ ---
5
+
6
+ # Clawrise Core
7
+
8
+ Treat Clawrise as the local execution layer, not as a cross-platform business schema layer.
9
+
10
+ This skill owns:
11
+
12
+ - setup and environment checks
13
+ - capability discovery through `doctor` and `spec`
14
+ - auth and account inspection
15
+ - generic execution rules
16
+
17
+ This skill does not own:
18
+
19
+ - Feishu-specific auth and task guidance
20
+ - Notion-specific auth and task guidance
21
+ - provider-specific field semantics beyond generic guardrails
22
+
23
+ ## Use This Skill When
24
+
25
+ - You need to confirm that a local `clawrise` CLI is available
26
+ - You need to run `setup <client> [platform...]`
27
+ - You need to inspect plugins, config, runtime state, or playbooks
28
+ - You need to discover available platforms or operations
29
+ - You need to inspect the input fields, examples, or constraints of one operation
30
+ - You need to execute a Clawrise operation
31
+
32
+ ## Workflow
33
+
34
+ 1. Prefer `clawrise` from `PATH`.
35
+ 2. If `clawrise` is not in `PATH`, but `npx` is available, use:
36
+
37
+ ```bash
38
+ npx @clawrise/clawrise-cli ...
39
+ ```
40
+
41
+ 3. If the host still needs initial setup, run:
42
+
43
+ ```bash
44
+ clawrise setup <client>
45
+ clawrise setup <client> <platform>
46
+ ```
47
+
48
+ or:
49
+
50
+ ```bash
51
+ npx @clawrise/clawrise-cli setup <client>
52
+ npx @clawrise/clawrise-cli setup <client> <platform>
53
+ ```
54
+
55
+ 4. If `clawrise` is not in `PATH`, but the current workspace is this repository, fall back to:
56
+
57
+ ```bash
58
+ GOCACHE=/tmp/clawrise-go-build GOMODCACHE=/tmp/clawrise-gomodcache go run ./cmd/clawrise ...
59
+ ```
60
+
61
+ 5. Start with:
62
+
63
+ ```bash
64
+ clawrise doctor
65
+ ```
66
+
67
+ 6. Then discover capabilities:
68
+
69
+ ```bash
70
+ clawrise spec list
71
+ clawrise spec list <path>
72
+ clawrise spec get <operation>
73
+ ```
74
+
75
+ 7. Inspect auth only when the task needs it:
76
+
77
+ ```bash
78
+ clawrise auth methods --platform <platform>
79
+ clawrise auth inspect <account>
80
+ clawrise auth check <account>
81
+ ```
82
+
83
+ 8. For write operations, always run `--dry-run` first and only perform the real call after the input shape is validated.
84
+
85
+ 9. When building input JSON, keep provider-native field names exactly as defined by the operation. Do not invent a unified cross-platform schema.
86
+
87
+ 10. If the task is Feishu-specific or Notion-specific, use the matching platform skill together with this one.
88
+
89
+ ## Read These References Only When Needed
90
+
91
+ - `references/workflow.md`
92
+ - `references/install-and-layout.md`
@@ -0,0 +1,105 @@
1
+ # Installation And Layout
2
+
3
+ ## 1. Repository Skill Source
4
+
5
+ The source directories inside this repository are:
6
+
7
+ ```text
8
+ skills/clawrise-core
9
+ skills/clawrise-feishu
10
+ skills/clawrise-notion
11
+ ```
12
+
13
+ ## 2. Client Skill Locations
14
+
15
+ Default shared install targets are:
16
+
17
+ ```text
18
+ ~/.codex/skills/<skill-name>
19
+ ~/.claude/skills/<skill-name>
20
+ ~/.openclaw/skills/<skill-name>
21
+ ~/.config/opencode/skills/<skill-name>
22
+ ```
23
+
24
+ Project-local installs may use client-specific directories such as:
25
+
26
+ ```text
27
+ ./.claude/skills/<skill-name>
28
+ ./skills/<skill-name>
29
+ ./.opencode/skills/<skill-name>
30
+ ```
31
+
32
+ The exact target is selected by:
33
+
34
+ ```bash
35
+ clawrise setup <client> [platform...]
36
+ ```
37
+
38
+ or:
39
+
40
+ ```bash
41
+ npx @clawrise/clawrise-cli setup <client> [platform...]
42
+ ```
43
+
44
+ ## 3. Default Clawrise Runtime Paths
45
+
46
+ In this project, `clawrise doctor` exposes these default paths:
47
+
48
+ - config file: `~/.clawrise/config.yaml`
49
+ - state directory: `~/.clawrise/state`
50
+ - runtime directory: `~/.clawrise/state/runtime`
51
+ - repo-local plugin directory: `.clawrise/plugins`
52
+ - user plugin directory: `~/.clawrise/plugins`
53
+
54
+ Always trust the live `clawrise doctor` output over static assumptions.
55
+
56
+ ## 4. Plugin Install Sources
57
+
58
+ Clawrise currently supports:
59
+
60
+ - `file://`
61
+ - `https://`
62
+ - `npm://`
63
+
64
+ Useful commands:
65
+
66
+ ```bash
67
+ clawrise plugin list
68
+ clawrise plugin install <source>
69
+ clawrise plugin verify --all
70
+ ```
71
+
72
+ ## 5. Repository Install Script
73
+
74
+ This repository provides:
75
+
76
+ ```bash
77
+ ./scripts/skills/setup-local-codex.sh
78
+ ```
79
+
80
+ It copies the repository skills into a local Codex skill directory for repository-level testing.
81
+
82
+ Restart Codex after installation so the new skills are loaded.
83
+
84
+ ## 6. No-Clone Distribution Options
85
+
86
+ Recommended non-clone channels are:
87
+
88
+ - website-hosted versioned skill archives
89
+ - npm package bundled with the `skills/` directory
90
+
91
+ For website distribution, publish:
92
+
93
+ - a skill manifest such as `index.json`
94
+ - versioned archives such as `<version>/<skill-name>.tar.gz`
95
+ - one install script that downloads and expands skills into `~/.codex/skills`
96
+
97
+ For npm distribution, prefer setup commands such as:
98
+
99
+ ```bash
100
+ clawrise setup codex
101
+ clawrise setup codex feishu
102
+ clawrise setup claude-code notion --skills-dir ./.claude/skills
103
+ ```
104
+
105
+ Do not use automatic `postinstall` hooks to write into the user's Codex directory.
@@ -0,0 +1,130 @@
1
+ # Clawrise General Workflow
2
+
3
+ ## 1. Ensure Setup Has Been Run
4
+
5
+ If the user is on a fresh machine or the current client has not been prepared yet, start with:
6
+
7
+ ```bash
8
+ clawrise setup <client>
9
+ clawrise setup <client> <platform>
10
+ ```
11
+
12
+ or:
13
+
14
+ ```bash
15
+ npx @clawrise/clawrise-cli setup <client>
16
+ npx @clawrise/clawrise-cli setup <client> <platform>
17
+ ```
18
+
19
+ Use platform setup only when the user actually needs that platform.
20
+
21
+ Examples:
22
+
23
+ - `setup codex`
24
+ - `setup codex feishu`
25
+ - `setup openclaw notion`
26
+
27
+ ## 2. Inspect The Environment First
28
+
29
+ Start with:
30
+
31
+ ```bash
32
+ clawrise doctor
33
+ ```
34
+
35
+ This command tells you:
36
+
37
+ - config file path
38
+ - state and runtime paths
39
+ - plugin discovery roots
40
+ - discovered plugins and their health
41
+ - playbook validation status
42
+
43
+ Do not assume any of these before checking `doctor`:
44
+
45
+ - a platform plugin is installed
46
+ - a default account exists
47
+ - local config is already complete
48
+
49
+ ## 3. Discover Before Building Input
50
+
51
+ Preferred sequence:
52
+
53
+ ```bash
54
+ clawrise spec list
55
+ clawrise spec list feishu
56
+ clawrise spec list notion
57
+ clawrise spec get <operation>
58
+ ```
59
+
60
+ If the task spans many operations, use:
61
+
62
+ ```bash
63
+ clawrise spec export <path> --format markdown
64
+ clawrise docs generate <path> --out-dir <dir>
65
+ ```
66
+
67
+ `spec get` is the most important fact source when you need to build one concrete call.
68
+
69
+ ## 4. Inspect Auth And Accounts
70
+
71
+ Useful commands:
72
+
73
+ ```bash
74
+ clawrise auth methods --platform <platform>
75
+ clawrise auth inspect <account>
76
+ clawrise auth check <account>
77
+ clawrise account list
78
+ clawrise account inspect <name>
79
+ ```
80
+
81
+ If the user does not explicitly provide an account, do not assume the default account is valid. Check `doctor` or `account current` first.
82
+
83
+ ## 5. Execution Rules
84
+
85
+ Recommended order:
86
+
87
+ ```bash
88
+ clawrise <operation> --dry-run --json '<payload>'
89
+ clawrise <operation> --json '<payload>'
90
+ ```
91
+
92
+ Common flags include:
93
+
94
+ - `--account`
95
+ - `--subject`
96
+ - `--json`
97
+ - `--input`
98
+ - `--timeout`
99
+ - `--dry-run`
100
+ - `--idempotency-key`
101
+ - `--quiet`
102
+
103
+ ## 6. Output Shape
104
+
105
+ Execution output is a normalized JSON envelope. Key fields include:
106
+
107
+ - `ok`
108
+ - `operation`
109
+ - `context`
110
+ - `data`
111
+ - `error`
112
+ - `meta`
113
+ - `idempotency`
114
+
115
+ If a downstream step only needs the success payload, use `--quiet`.
116
+
117
+ ## 7. Architectural Boundary
118
+
119
+ Clawrise unifies the execution layer, not the business resource model.
120
+
121
+ That means:
122
+
123
+ - Build Feishu inputs with Feishu-native fields
124
+ - Build Notion inputs with Notion-native fields
125
+ - Do not compress calendars, pages, documents, or records into one invented JSON schema
126
+
127
+ If the user needs platform-specific auth or task guidance, switch to the matching platform skill after setup:
128
+
129
+ - `clawrise-feishu`
130
+ - `clawrise-notion`
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: clawrise-feishu
3
+ description: Use when the task is to access Feishu through Clawrise, including Feishu auth setup, calendar events, docs updates, bitable records, wiki nodes, contacts, or any other `feishu.*` operation. Pair with clawrise-core.
4
+ ---
5
+
6
+ # Clawrise Feishu
7
+
8
+ This skill adds Feishu-specific guidance. Use `clawrise-core` for the common execution workflow.
9
+
10
+ This skill assumes that the current client has already been prepared with:
11
+
12
+ ```bash
13
+ clawrise setup <client> feishu
14
+ ```
15
+
16
+ or:
17
+
18
+ ```bash
19
+ npx @clawrise/clawrise-cli setup <client> feishu
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ 1. Start with the `clawrise-core` workflow to inspect the local environment and specs.
25
+ 2. Add this skill only when the task is Feishu-specific.
26
+ 3. Do not use this skill to explain generic client setup unless the user is explicitly setting up Feishu support.
27
+
28
+ ## Check These First
29
+
30
+ ```bash
31
+ clawrise spec list feishu
32
+ clawrise auth methods --platform feishu
33
+ ```
34
+
35
+ ## Auth Constraints
36
+
37
+ - `feishu.app_credentials`
38
+ - for `bot`
39
+ - `feishu.oauth_user`
40
+ - for `user`
41
+
42
+ If the user does not explicitly say whether the task should use a bot or a user identity, do not guess. Inspect the account config and auth method first.
43
+
44
+ ## Task Rules
45
+
46
+ - Run `clawrise spec get <operation>` before building JSON
47
+ - Prefer `--dry-run` for write operations
48
+ - Read before write to avoid overwriting existing data
49
+ - Prefer RFC3339 for time fields
50
+
51
+ ## Read This Reference Only When The Task Matches
52
+
53
+ - `references/common-tasks.md`
@@ -0,0 +1,80 @@
1
+ # Feishu Common Tasks
2
+
3
+ This reference assumes that `clawrise-core` and `clawrise-feishu` have already been installed for the current client.
4
+
5
+ If the user still needs Feishu support installed, run:
6
+
7
+ ```bash
8
+ clawrise setup <client> feishu
9
+ ```
10
+
11
+ ## Auth Methods
12
+
13
+ Current Feishu auth methods include:
14
+
15
+ - `feishu.app_credentials`
16
+ - `subject=bot`
17
+ - requires `app_id` and `app_secret`
18
+ - `feishu.oauth_user`
19
+ - `subject=user`
20
+ - requires `client_id` and `client_secret`
21
+ - supports interactive login
22
+
23
+ Check first:
24
+
25
+ ```bash
26
+ clawrise auth methods --platform feishu
27
+ ```
28
+
29
+ ## High-Signal Tasks
30
+
31
+ ### 1. Create Or Update A Feishu Calendar Event
32
+
33
+ Start with:
34
+
35
+ - `feishu.calendar.event.create`
36
+ - `feishu.calendar.event.get`
37
+ - `feishu.calendar.event.update`
38
+
39
+ Playbook:
40
+
41
+ - `docs/playbooks/en/feishu-calendar-event-upsert.md`
42
+
43
+ ### 2. Update A Feishu Document
44
+
45
+ Start with:
46
+
47
+ - `feishu.docs.document.get`
48
+ - `feishu.docs.document.get_raw_content`
49
+ - `feishu.docs.document.edit`
50
+
51
+ Playbook:
52
+
53
+ - `docs/playbooks/en/feishu-document-update.md`
54
+
55
+ ### 3. Create Or Update A Feishu Bitable Record
56
+
57
+ Start with:
58
+
59
+ - `feishu.bitable.record.list`
60
+ - `feishu.bitable.record.create`
61
+ - `feishu.bitable.record.update`
62
+
63
+ Playbook:
64
+
65
+ - `docs/playbooks/en/feishu-bitable-record-upsert.md`
66
+
67
+ ## Suggested Flow
68
+
69
+ For any concrete task, prefer:
70
+
71
+ ```bash
72
+ clawrise spec get <operation>
73
+ clawrise <operation> --dry-run --json '<payload>'
74
+ ```
75
+
76
+ If the user describes a business intent without naming the operation, start with:
77
+
78
+ ```bash
79
+ clawrise spec list feishu
80
+ ```
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: clawrise-notion
3
+ description: Use when the task is to access Notion through Clawrise, including Notion auth setup, page updates, markdown updates, data source queries, comments, blocks, or any other `notion.*` operation. Pair with clawrise-core.
4
+ ---
5
+
6
+ # Clawrise Notion
7
+
8
+ This skill adds Notion-specific guidance. Use `clawrise-core` for the common execution workflow.
9
+
10
+ This skill assumes that the current client has already been prepared with:
11
+
12
+ ```bash
13
+ clawrise setup <client> notion
14
+ ```
15
+
16
+ or:
17
+
18
+ ```bash
19
+ npx @clawrise/clawrise-cli setup <client> notion
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ 1. Start with the `clawrise-core` workflow to inspect the local environment and specs.
25
+ 2. Add this skill only when the task is Notion-specific.
26
+ 3. Do not use this skill to explain generic client setup unless the user is explicitly setting up Notion support.
27
+
28
+ ## Check These First
29
+
30
+ ```bash
31
+ clawrise spec list notion
32
+ clawrise auth methods --platform notion
33
+ ```
34
+
35
+ ## Auth Constraints
36
+
37
+ - `notion.internal_token`
38
+ - for `integration`
39
+ - `notion.oauth_public`
40
+ - for `integration`
41
+
42
+ Both current Notion auth methods use the `integration` subject. Do not switch to `bot` or `user`.
43
+
44
+ ## Task Rules
45
+
46
+ - Run `clawrise spec get <operation>` before building JSON
47
+ - Prefer `--dry-run` for write operations
48
+ - Read before write to avoid overwriting page or block content
49
+ - Keep pages, blocks, comments, and data sources in Notion-native fields
50
+
51
+ ## Read This Reference Only When The Task Matches
52
+
53
+ - `references/common-tasks.md`
@@ -0,0 +1,68 @@
1
+ # Notion Common Tasks
2
+
3
+ This reference assumes that `clawrise-core` and `clawrise-notion` have already been installed for the current client.
4
+
5
+ If the user still needs Notion support installed, run:
6
+
7
+ ```bash
8
+ clawrise setup <client> notion
9
+ ```
10
+
11
+ ## Auth Methods
12
+
13
+ Current Notion auth methods include:
14
+
15
+ - `notion.internal_token`
16
+ - `subject=integration`
17
+ - requires `token`
18
+ - `notion.oauth_public`
19
+ - `subject=integration`
20
+ - requires `client_id` and `client_secret`
21
+ - supports interactive login
22
+
23
+ Check first:
24
+
25
+ ```bash
26
+ clawrise auth methods --platform notion
27
+ ```
28
+
29
+ ## High-Signal Tasks
30
+
31
+ ### 1. Update A Page Title, Properties, Or Body
32
+
33
+ Start with:
34
+
35
+ - `notion.page.get`
36
+ - `notion.page.update`
37
+ - `notion.page.markdown.get`
38
+ - `notion.page.markdown.update`
39
+
40
+ Playbook:
41
+
42
+ - `docs/playbooks/en/notion-page-update.md`
43
+
44
+ ### 2. Query A Data Source
45
+
46
+ Start with:
47
+
48
+ - `notion.data_source.get`
49
+ - `notion.data_source.query`
50
+
51
+ Playbook:
52
+
53
+ - `docs/playbooks/en/notion-data-source-query.md`
54
+
55
+ ## Suggested Flow
56
+
57
+ For any concrete task, prefer:
58
+
59
+ ```bash
60
+ clawrise spec get <operation>
61
+ clawrise <operation> --dry-run --json '<payload>'
62
+ ```
63
+
64
+ If the user describes a business intent without naming the operation, start with:
65
+
66
+ ```bash
67
+ clawrise spec list notion
68
+ ```