@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 +9 -3
- package/bin/clawrise.js +16 -1
- package/lib/platform.js +51 -11
- package/lib/setup.js +376 -0
- package/package.json +18 -8
- package/skills/clawrise-core/SKILL.md +92 -0
- package/skills/clawrise-core/references/install-and-layout.md +105 -0
- package/skills/clawrise-core/references/workflow.md +130 -0
- package/skills/clawrise-feishu/SKILL.md +53 -0
- package/skills/clawrise-feishu/references/common-tasks.md +80 -0
- package/skills/clawrise-notion/SKILL.md +53 -0
- package/skills/clawrise-notion/references/common-tasks.md +68 -0
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# @clawrise/clawrise-cli
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
|
6
|
-
'darwin:arm64': '
|
|
7
|
-
'darwin:x64': '
|
|
8
|
-
'linux:arm64': '
|
|
9
|
-
'linux:x64': '
|
|
10
|
-
'win32:arm64': '
|
|
11
|
-
'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
|
|
17
|
+
const packageSuffix = platformSuffixMap[platformKey];
|
|
17
18
|
|
|
18
|
-
if (!
|
|
19
|
-
throw new Error(
|
|
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(
|
|
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.
|
|
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.
|
|
24
|
-
"@clawrise/clawrise-cli-darwin-x64": "0.1.0-alpha.
|
|
25
|
-
"@clawrise/clawrise-cli-linux-arm64": "0.1.0-alpha.
|
|
26
|
-
"@clawrise/clawrise-cli-linux-x64": "0.1.0-alpha.
|
|
27
|
-
"@clawrise/clawrise-cli-win32-arm64": "0.1.0-alpha.
|
|
28
|
-
"@clawrise/clawrise-cli-win32-x64": "0.1.0-alpha.
|
|
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
|
+
```
|