@tmddev/tmd 0.2.0 → 0.3.1

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
@@ -38,7 +38,7 @@ At the core of TMD is the principle that tasks should be **pee-break (10 seconds
38
38
  - **PDCA Cycle Management**: Four-phase commands for Plan, Do, Check, and Act
39
39
  - **Pipe Execution**: Automated PDCA cycles without human input for CI/CD and AI agent workflows
40
40
  - **Ten sec to Ten min Task!**: Tasks are designed to be pee-break (10 seconds to 10 minutes) sized for quick completion
41
- - **OpenSpec Integration**: Automatic creation and linking of OpenSpec change proposals
41
+ - **Built-in Spec Engine**: OpenSpec-compatible specs/changes without external `openspec`
42
42
  - **Skills System**: Reusable capabilities for AI agents with cross-agent invocation support
43
43
  - **Step Executors**: Built-in executors for bash commands, file operations, and API calls
44
44
  - **English Language Standard**: All documents and specifications use English
@@ -102,10 +102,17 @@ Optional:
102
102
  - **`pnpm build:native`** — Rebuild only the `tmd-skills` Rust binary (faster when only Rust code changed).
103
103
  - **`./bin/agent-browser install`** — When using the agent-browser skill, install the agent-browser CLI if this script is provided (e.g. by the agent-browser project; skip if not present).
104
104
 
105
- Example: add the `pdf` skill from [anthropics/skills](https://github.com/anthropics/skills) and symlink to all detected agents:
105
+ Example: install a skill from an ecosystem repo (defaults to `npx skills`), then sync into TMD layout + DB:
106
106
 
107
107
  ```bash
108
- tmd skills add anthropics/skills --github --skill pdf --all
108
+ # List skills in a repo
109
+ tmd skills add vercel-labs/agent-skills --list
110
+
111
+ # Install a specific skill to the current project (non-interactive)
112
+ tmd skills add vercel-labs/agent-skills --skill web-design-guidelines -y
113
+
114
+ # If the skill was installed outside the detected canonical store, or the Desktop UI doesn't show it yet:
115
+ tmd skills sync --all
109
116
  ```
110
117
 
111
118
  ## Quick Start
@@ -198,222 +205,36 @@ This principle ensures tasks are:
198
205
 
199
206
  ## Commands
200
207
 
201
- ### Setup and Dashboard
202
-
203
- - `tmd init [path]` - Initialize TMD in your project (creates `tmd/` and `schemas/pdca/` when missing; default path `.`)
204
- - `tmd view` - Display a dashboard of tasks by phase and status
205
- - `tmd validate [task-id]` - Validate task documents or PDCA schemas
206
- - `--schemas [name]` - Validate schemas only (name optional)
207
- - `--all` - Validate all tasks and schemas
208
- - `--strict` - Stricter checks (e.g. task size)
209
- - `--json` - Output as JSON
210
- - `tmd schemas` - List available workflow schemas
211
- - `--json` - Output as JSON
212
-
213
- ### PDCA Commands
214
-
215
- - `tmd plan <description>` / `tmdp` - Create a new plan
216
- - `--openspec` - Create or link OpenSpec change proposal
217
- - `--skill` - Create skill definition
218
- - `--use-skill <skill-name>` - Use existing skill
219
- - `--validate-tasks` - Validate task size: pee-break (10 seconds to 10 minutes)
220
-
221
- - `tmd do <task-id>` / `tmdd` - Execute actions
222
- - `--data <key=value>` - Record data
223
- - `--skill <skill-name>` - Execute skill
224
-
225
- - `tmd check <task-id>` / `tmdc` - Evaluate results
226
- - `--compare` - Automatic comparison
227
- - `--validate-skill` - Validate skill execution
228
-
229
- - `tmd act <task-id>` / `tmda` - Take improvement actions
230
- - `--standardize` - Generate standardization document
231
- - `--complete` - Mark task as completed
232
-
233
- ### Task Management
234
-
235
- - `tmd list` - List all tasks
236
- - `--status <status>` - Filter by status
237
- - `--phase <phase>` - Filter by phase
238
-
239
- - `tmd show <task-id>` - Show task details
240
-
241
- ### Pipe (Automated PDCA)
242
-
243
- - `tmd pipe init <task-id>` - Initialize pipe configuration
244
- - `--force` - Overwrite existing configuration
245
-
246
- - `tmd pipe run <task-id>` - Run full PDCA cycle automatically
247
- - `--from <phase>` - Start from specific phase (do, check, act)
248
- - `--dry-run` - Preview execution without making changes
249
-
250
- - `tmd pipe status <task-id>` - Show pipe execution state
251
- - `--json` - Output in JSON format
252
-
253
- ### Skills Management
254
-
255
- - `tmd skills list` - List all available skills
256
- - `--tag <tag>` - Filter by tag (repeatable, OR semantics)
257
- - `tmd skills search <query>` - Search skills
258
- - `tmd skills show <skill-name>` - Show skill details
259
- - `tmd skills invoke <skill-name> --input <params>` - Invoke a skill
260
- - `tmd skills create <name>` - Create a skill (optionally `--description <desc>`, `--tags <t1,t2>`)
261
- - `tmd skills update <name>` - Update metadata (`--description <desc>`, `--tags <t1,t2>`; at least one required)
262
- - `tmd skills remove <name>` - Remove a skill (`--force` to skip confirmation)
263
-
264
- ## Skills System
265
-
266
- Skills are reusable capabilities for AI agents that can be defined, shared, and executed within PDCA cycles.
267
-
268
- ### Creating a Skill
269
-
270
- ```bash
271
- tmd plan "As a developer, I want to generate README files in multiple languages, so as to make the project accessible to international contributors" --skill
272
- ```
273
-
274
- This creates a skill with:
275
- - User story format
276
- - Executable steps definition
277
- - Configuration
278
- - Metadata for AI agent discovery
279
-
280
- ### Example: README Generation Skill
281
-
282
- ```yaml
283
- # tmd/skills/generate-readme-multilang/metadata.yaml
284
- name: generate-readme-multilang
285
- version: 1.0.0
286
- description: Generate README files in multiple languages
287
- interface:
288
- input:
289
- - name: template_path
290
- type: string
291
- required: true
292
- description: Path to README.md template
293
- - name: target_languages
294
- type: array
295
- required: true
296
- description: List of target languages (e.g., ["zh", "es", "fr"])
297
- output:
298
- generated_files: array of file paths
299
- validation_status: enum (passed/failed)
300
- language_index_updated: boolean
301
- ```
302
-
303
- ### Cross-Agent Invocation
304
-
305
- Skills can be invoked by any AI agent:
306
-
307
- ```bash
308
- tmd skill invoke generate-readme-multilang --input "template_path=README.md target_languages=[zh,es,fr]"
309
- ```
310
-
311
- ## Pipe Execution
312
-
313
- Pipe execution enables fully automated PDCA cycles without human intervention - ideal for CI/CD integration and AI agent workflows.
314
-
315
- ### Initialize Pipe
316
-
317
- ```bash
318
- tmd pipe init <task-id>
319
- ```
320
-
321
- This creates a `pipeline.yaml` configuration file in the task's plan directory with customizable settings for each phase.
208
+ For a full reference, run `tmd --help` (and `tmd <command> --help`), or see `docs/`.
322
209
 
323
- ### Run Full Pipe
210
+ ### Common workflow (PDCA)
324
211
 
325
212
  ```bash
326
- tmd pipe run <task-id>
327
- ```
328
-
329
- This automatically executes:
330
- 1. **Do phase**: Executes all tasks, runs skill steps, captures output
331
- 2. **Check phase**: Compares results against goals, analyzes deviations
332
- 3. **Act phase**: Processes results, generates improvements, marks task complete
333
-
334
- ### Pipeline Configuration
335
-
336
- ```yaml
337
- # pipeline.yaml
338
- version: "1.0"
339
- phases:
340
- do:
341
- auto: true
342
- parallel: false
343
- maxConcurrency: 4
344
- successCriteria:
345
- minTasksCompleted: "100%"
346
- check:
347
- auto: true
348
- analyze: true
349
- recommend: true
350
- act:
351
- auto: true
352
- standardize: true
353
- carryForward: true
354
- completeOnSuccess: true
355
- ```
356
-
357
- ### Step Executors
358
-
359
- Pipeline supports three step types for automated task execution:
360
-
361
- - **bash**: Execute shell commands
362
- ```yaml
363
- - type: bash
364
- command: "npm run build"
365
- ```
366
-
367
- - **file**: File operations (read, write, copy, delete)
368
- ```yaml
369
- - type: file
370
- operation: write
371
- path: output.txt
372
- content: "Hello World"
373
- ```
374
-
375
- - **api**: HTTP requests
376
- ```yaml
377
- - type: api
378
- url: "https://api.example.com/data"
379
- method: POST
380
- body: { "key": "value" }
381
- ```
382
-
383
- ### Dry Run Mode
384
-
385
- Preview pipe execution without making changes:
386
-
387
- ```bash
388
- tmd pipe run <task-id> --dry-run
213
+ tmd init
214
+ tmd plan "Describe the work"
215
+ tmd do <task-id>
216
+ tmd check <task-id>
217
+ tmd act <task-id>
389
218
  ```
390
219
 
391
- ### Resume from Phase
392
-
393
- Start from a specific phase (useful for recovering from failures):
394
-
395
- ```bash
396
- tmd pipe run <task-id> --from check
397
- ```
220
+ ### Skills (npx-first)
398
221
 
399
- ## OpenSpec Integration
222
+ - `tmd skills add <source>` defaults to the ecosystem CLI (`npx skills add`) and then syncs to:
223
+ - `{project_root}/.agents/skills/<name>`
224
+ - `{project_root}/.tmd/skills/<name>`
225
+ - `{project_root}/.tmd/skills.db`
226
+ - `tmd skills sync` re-syncs the detected canonical store into TMD layout + DB.
400
227
 
401
- TMD automatically integrates with OpenSpec projects:
228
+ See [`docs/skills.md`](docs/skills.md) for commands, flags, canonical store discovery rules, and troubleshooting.
402
229
 
403
- ```bash
404
- tmd plan "Description" --openspec
405
- ```
230
+ ### Desktop
406
231
 
407
- This:
408
- - Detects OpenSpec project structure
409
- - Creates OpenSpec change proposal
410
- - Links TMD task to OpenSpec change
411
- - Maintains bidirectional traceability
232
+ - `tmd ui` launches the Desktop app (browse tasks, skills, agents, config)
412
233
 
413
234
  ## Directory Structure
414
235
 
415
236
  ```
416
- tmd/
237
+ .tmd/
417
238
  ├── plan/
418
239
  │ └── [task-id]/
419
240
  │ ├── plan.md
@@ -520,6 +341,36 @@ Pipe: 20260123-build-and-deploy-application
520
341
  Pipe completed successfully
521
342
  ```
522
343
 
344
+ ### Example 4: Feishu CLI Integration
345
+
346
+ ```bash
347
+ # List available Feishu chats
348
+ tmd feishu chats
349
+
350
+ # List chats in JSON format
351
+ tmd feishu chats --json
352
+
353
+ # Get messages from a chat
354
+ tmd feishu messages --chat-id oc_1234567890abcdef
355
+
356
+ # Get messages with pagination and sorting
357
+ tmd feishu messages --chat-id oc_1234567890abcdef --page-size 20 --sort-type ByCreateTimeAsc
358
+
359
+ # Send a message to a Feishu chat
360
+ tmd feishu message send --chat-id oc_1234567890abcdef --message "Hello from TMD!"
361
+
362
+ # Reply to a message
363
+ tmd feishu message reply --message-id om_1234567890abcdef --message "This is a reply"
364
+
365
+ # Get a specific message
366
+ tmd feishu message get --message-id om_1234567890abcdef
367
+
368
+ # Get message in JSON format
369
+ tmd feishu message get --message-id om_1234567890abcdef --json
370
+ ```
371
+
372
+ **Note**: Feishu commands require credentials to be configured. Use `tmd ui` to open the desktop application and configure `feishu_app_id` and `feishu_app_secret` in Settings.
373
+
523
374
  ## Language Standard
524
375
 
525
376
  All documents and specifications use English. The system:
@@ -576,16 +427,6 @@ TMD follows the PDCA (Plan-Do-Check-Act) cycle:
576
427
  └────────────────────┘
577
428
  ```
578
429
 
579
- ## Task Size Principle
580
-
581
- **Ten seconds to Ten minutes Task Markdown Driven Development!**
582
-
583
- Tasks should be **pee-break (10 seconds to 10 minutes)** sized. This ensures:
584
- - Tasks are atomic and completable
585
- - Progress tracking is meaningful
586
- - No complex multi-step coordination required
587
- - Agent-friendly for AI autonomous execution
588
-
589
430
  ## Contributing
590
431
 
591
432
  Contributions are welcome! Please ensure all documentation follows the English language standard.
package/dist/cli.js CHANGED
@@ -10,11 +10,17 @@ import { actCommand } from './commands/act.js';
10
10
  import { listCommand } from './commands/list.js';
11
11
  import { showCommand } from './commands/show.js';
12
12
  import { skillsCommand } from './commands/skills.js';
13
+ import { knowledgeCommand } from './commands/knowledge.js';
13
14
  import { pipelineInitCommand, pipelineRunCommand, pipelineStatusCommand } from './commands/pipeline.js';
14
15
  import { initCommand } from './commands/init.js';
16
+ import { uiCommand } from './commands/ui.js';
15
17
  import { viewCommand } from './commands/view.js';
16
18
  import { validateCommand } from './commands/validate.js';
17
19
  import { schemasCommand } from './commands/schemas.js';
20
+ import { specArchiveCommand, specListCommand, specShowCommand, specValidateCommand } from './commands/spec.js';
21
+ import { feishuChatsCommand, feishuMessagesCommand, feishuMessageSendCommand, feishuMessageReplyCommand, feishuMessageGetCommand, feishuDocumentsGetCommand, feishuBitableGetCommand, feishuBitableTablesCommand, feishuBitableViewsCommand, feishuBitableViewCommand, feishuBitableRecordsCommand, feishuBitableRecordCommand } from './commands/feishu.js';
22
+ import { configCommand } from './commands/config.js';
23
+ import { serverCommand } from './commands/server.js';
18
24
  const program = new Command();
19
25
  // Resolve project root: bin/tmd.js -> dist/cli.js -> dist/ -> project root
20
26
  const __filename = fileURLToPath(import.meta.url);
@@ -32,10 +38,23 @@ program
32
38
  .description('Initialize TMD in your project')
33
39
  .argument('[path]', 'Target path', '.')
34
40
  .action((pathArg) => { initCommand(pathArg); });
41
+ program
42
+ .command('ui')
43
+ .description('Launch the TMD Desktop app (current directory as project root; creates .tmd and .agents if missing)')
44
+ .action(uiCommand);
35
45
  program
36
46
  .command('view')
37
47
  .description('Display a dashboard of tasks by phase and status')
38
48
  .action(viewCommand);
49
+ program
50
+ .command('server')
51
+ .description('Run local HTTP server (Rust tmd-server)')
52
+ .option('--host <host>', 'Bind host (default: 127.0.0.1)', '127.0.0.1')
53
+ .option('--port <port>', 'Bind port (default: 13300)', (v) => parseInt(v, 10), 13300)
54
+ .option('--project-root <path>', 'Project root (default: cwd)')
55
+ .action((opts) => {
56
+ serverCommand(opts);
57
+ });
39
58
  program
40
59
  .command('validate')
41
60
  .description('Validate task documents or PDCA schemas')
@@ -50,16 +69,50 @@ program
50
69
  .description('List available workflow schemas')
51
70
  .option('--json', 'Output as JSON')
52
71
  .action((opts) => { schemasCommand(opts); });
72
+ // Spec commands (built-in spec engine)
73
+ const spec = program
74
+ .command('spec')
75
+ .description('Manage specs and changes (list, show, validate, archive)');
76
+ spec
77
+ .command('list')
78
+ .description('List specs')
79
+ .option('--json', 'Output as JSON')
80
+ .action((opts) => { specListCommand(opts); });
81
+ spec
82
+ .command('show')
83
+ .description('Show a spec')
84
+ .argument('<spec-id>', 'Spec ID')
85
+ .option('--json', 'Output as JSON')
86
+ .action((specId, opts) => { specShowCommand(specId, opts); });
87
+ spec
88
+ .command('validate')
89
+ .description('Validate specs/changes')
90
+ .argument('[item]', 'Spec ID or change ID')
91
+ .option('--all', 'Validate all specs and changes')
92
+ .option('--specs', 'Validate specs only')
93
+ .option('--changes', 'Validate changes only')
94
+ .option('--strict', 'Strict validation')
95
+ .option('--no-interactive', 'Disable prompts')
96
+ .option('--json', 'Output as JSON')
97
+ .action((item, opts) => { specValidateCommand(item, opts); });
98
+ spec
99
+ .command('archive')
100
+ .description('Archive a change and apply deltas')
101
+ .argument('<change-id>', 'Change ID to archive')
102
+ .option('--yes', 'Skip confirmation')
103
+ .action((changeId, opts) => { specArchiveCommand(changeId, opts); });
53
104
  // PDCA commands
54
105
  program
55
106
  .command('plan')
56
107
  .alias('p')
57
- .description('Plan phase: Define objectives, analyze problems, and create plans')
108
+ .description('Plan phase: Define objectives, analyze problems, and create plans with LLM')
58
109
  .argument('<description>', 'Task description')
59
- .option('--openspec', 'Create or link OpenSpec change proposal')
110
+ .option('--agent-id <id>', 'Agent to use for planning (default: planner)', 'planner')
111
+ .option('--assign-agent <id>', 'Assign planned tasks to agent id (default: executor)')
60
112
  .option('--skill', 'Create skill definition')
61
113
  .option('--use-skill <skill-name>', 'Use existing skill')
62
114
  .option('--validate-tasks', 'Validate task size: pee-break (10 seconds to 10 minutes)')
115
+ .option('--strict-deps', 'Fail fast when execution plan dependency validation fails')
63
116
  .action(planCommand);
64
117
  program
65
118
  .command('do')
@@ -109,22 +162,127 @@ program
109
162
  // Skills commands
110
163
  program
111
164
  .command('skills')
112
- .description('Manage skills (list, search, show, invoke, add, create, update, remove)')
113
- .argument('[action]', 'Action: list, search, show, invoke, add, create, update, remove')
165
+ .description('Manage skills (list, search, show, invoke, add, find, check, update, init, generate-lock, sync, create, remove)')
166
+ .argument('[action]', 'Action: list, search, show, invoke, add, find, check, update, init, generate-lock, sync, create, remove')
114
167
  .argument('[name]', 'Skill name, search query, or repository (owner/repo)')
115
168
  .option('--input <params>', 'Input parameters for invoke')
116
- .option('--skill <skill-name>', 'Skill name when adding from repository')
169
+ .option('--skill <skill-name>', 'Skill name (npx skills add --skill)')
170
+ .option('-a, --agent <agent>', 'Target agent for npx skills (repeatable)', (v, prev) => (prev ?? []).concat([v]))
171
+ .option('-g, --global', 'Use global scope for npx skills')
172
+ .option('-y, --yes', 'Skip prompts for npx skills')
173
+ .option('-l, --list', 'List skills in a repository (npx skills add --list)')
117
174
  .option('--description <desc>', 'Description for create/update')
118
175
  .option('--tags <t1,t2>', 'Comma-separated tags for create/update')
119
176
  .option('--tag <tag>', 'Filter list by tag (repeatable)', (v, prev) => (prev ?? []).concat([v]))
120
177
  .option('--force', 'Remove without confirmation, or overwrite existing skill on add')
121
178
  .option('--all', 'With remove: also delete agent/IDE links. With create/add/update: also create symlinks under .cursor, .agents, .codex, .opencode, etc. so the skill is available to those IDEs')
122
- .option('--github', 'Import skill from GitHub repository (not skills.sh)')
179
+ .option('--github', 'Import skill from GitHub repository')
123
180
  .option('--branch <branch>', 'GitHub branch to fetch from (default: main/master)')
124
181
  .option('--path <path>', 'Custom path to skill file in repository')
125
182
  .action(function (action, name) {
126
183
  void skillsCommand(action, name, this.opts());
127
184
  });
185
+ // Knowledge commands
186
+ program
187
+ .command('knowledge')
188
+ .description('Manage knowledge entries (create from directory)')
189
+ .option('--create', 'Create knowledge entry from directory')
190
+ .option('--knowledge-id <id>', 'Knowledge entry ID')
191
+ .option('--dir <directory>', 'Source directory containing txt/md files')
192
+ .option('--agent-id <id>', 'Agent ID to use for LLM summarization (default: summarizer). Agent LLM config is read from agents table.')
193
+ .action(function () {
194
+ const opts = this.opts();
195
+ if (opts['create']) {
196
+ void knowledgeCommand('create', opts);
197
+ }
198
+ else {
199
+ console.error('Please specify an action. Use --create to create knowledge from directory.');
200
+ process.exit(1);
201
+ }
202
+ });
203
+ // Config commands
204
+ const config = program
205
+ .command('config')
206
+ .description('Manage configurations (list, get, set, delete, search, history, rollback, export, import)');
207
+ config
208
+ .command('list')
209
+ .description('List all configurations')
210
+ .option('--page-no <number>', 'Page number', (v) => parseInt(v, 10))
211
+ .option('--page-size <number>', 'Page size', (v) => parseInt(v, 10))
212
+ .action(function () {
213
+ const opts = this.opts();
214
+ configCommand('list', undefined, opts);
215
+ });
216
+ config
217
+ .command('get')
218
+ .description('Get configuration (no arg: get default config; with arg: get key from default config)')
219
+ .argument('[key]', 'Key to get from default config (if omitted, returns entire default config)')
220
+ .action(function (key) {
221
+ // If key is provided, pass it; if not, pass undefined (Rust will handle it)
222
+ configCommand('get', key);
223
+ });
224
+ config
225
+ .command('set')
226
+ .description('Set configuration value (data-id defaults to "default" if not provided)')
227
+ .argument('<data-id-or-value>', 'Configuration data-id or value (if only one arg provided, data-id="default")')
228
+ .argument('[value]', 'Configuration value (if provided, first arg is data-id)')
229
+ .option('--type <type>', 'Configuration type (yaml, json, xml, properties, text)', 'yaml')
230
+ .action(function (dataIdOrValue, value) {
231
+ const opts = this.opts();
232
+ // If value is provided, first arg is data-id; otherwise first arg is value and data-id is "default"
233
+ if (value !== undefined) {
234
+ configCommand('set', dataIdOrValue, value, opts);
235
+ }
236
+ else {
237
+ configCommand('set', 'default', dataIdOrValue, opts);
238
+ }
239
+ });
240
+ config
241
+ .command('delete')
242
+ .description('Delete configuration')
243
+ .argument('<key>', 'Configuration key')
244
+ .action(function (key) {
245
+ configCommand('delete', key);
246
+ });
247
+ config
248
+ .command('search')
249
+ .description('Search configurations by keywords')
250
+ .argument('<keywords>', 'Search keywords')
251
+ .action(function (keywords) {
252
+ configCommand('search', keywords);
253
+ });
254
+ config
255
+ .command('history')
256
+ .description('Show configuration history')
257
+ .argument('<key>', 'Configuration key')
258
+ .action(function (key) {
259
+ configCommand('history', key);
260
+ });
261
+ config
262
+ .command('rollback')
263
+ .description('Rollback configuration to a specific history version')
264
+ .argument('<key>', 'Configuration key')
265
+ .argument('<nid>', 'History version ID (nid)')
266
+ .action(function (key, nid) {
267
+ configCommand('rollback', key, nid);
268
+ });
269
+ config
270
+ .command('export')
271
+ .description('Export configurations to ZIP file')
272
+ .option('--output <file>', 'Output file path', 'configs.zip')
273
+ .action(function () {
274
+ const opts = this.opts();
275
+ configCommand('export', undefined, opts);
276
+ });
277
+ config
278
+ .command('import')
279
+ .description('Import configurations from ZIP file')
280
+ .argument('<file>', 'ZIP file path')
281
+ .option('--policy <policy>', 'Import policy (abort, skip, overwrite)', 'abort')
282
+ .action(function (file) {
283
+ const opts = this.opts();
284
+ configCommand('import', file, opts);
285
+ });
128
286
  // Pipeline commands
129
287
  const pipe = program
130
288
  .command('pipe')
@@ -148,5 +306,133 @@ pipe
148
306
  .argument('<task-id>', 'Task ID')
149
307
  .option('--json', 'Output in JSON format')
150
308
  .action(pipelineStatusCommand);
309
+ // Feishu commands
310
+ const feishu = program
311
+ .command('feishu')
312
+ .description('Feishu (Lark) integration commands');
313
+ feishu
314
+ .command('chats')
315
+ .description('List available Feishu chats')
316
+ .option('--json', 'Output as JSON')
317
+ .action((opts) => {
318
+ feishuChatsCommand(opts.json ?? false);
319
+ });
320
+ feishu
321
+ .command('messages')
322
+ .description('Get message list from a chat')
323
+ .requiredOption('--chat-id <chat-id>', 'Chat ID')
324
+ .option('--page-size <size>', 'Page size (number of messages per page)')
325
+ .option('--sort-type <type>', 'Sort type (e.g., ByCreateTimeAsc, ByCreateTimeDesc)')
326
+ .option('--json', 'Output as JSON')
327
+ .action(function () {
328
+ const opts = this.opts();
329
+ feishuMessagesCommand(opts.chatId, opts.pageSize, opts.sortType, opts.json ?? false);
330
+ });
331
+ const feishuMessage = feishu
332
+ .command('message')
333
+ .description('Message operations');
334
+ feishuMessage
335
+ .command('send')
336
+ .description('Send a message to a Feishu chat')
337
+ .requiredOption('--chat-id <chat-id>', 'Chat ID')
338
+ .requiredOption('--message <message>', 'Message content')
339
+ .action(function () {
340
+ const opts = this.opts();
341
+ feishuMessageSendCommand(opts.chatId, opts.message);
342
+ });
343
+ feishuMessage
344
+ .command('reply')
345
+ .description('Reply to a Feishu message')
346
+ .requiredOption('--message-id <message-id>', 'Message ID to reply to')
347
+ .requiredOption('--message <message>', 'Reply message content')
348
+ .action(function () {
349
+ const opts = this.opts();
350
+ feishuMessageReplyCommand(opts.messageId, opts.message);
351
+ });
352
+ feishuMessage
353
+ .command('get')
354
+ .description('Get a specific Feishu message by message ID')
355
+ .requiredOption('--message-id <message-id>', 'Message ID')
356
+ .option('--json', 'Output as JSON')
357
+ .action(function () {
358
+ const opts = this.opts();
359
+ feishuMessageGetCommand(opts.messageId, opts.json ?? false);
360
+ });
361
+ const feishuDocuments = feishu
362
+ .command('documents')
363
+ .description('Document operations');
364
+ feishuDocuments
365
+ .command('get')
366
+ .description('Get document metadata or raw content')
367
+ .requiredOption('--document-id <document-id>', 'Document ID')
368
+ .option('--raw', 'Get raw content instead of metadata')
369
+ .option('--json', 'Output as JSON')
370
+ .action(function () {
371
+ const opts = this.opts();
372
+ feishuDocumentsGetCommand(opts.documentId, opts.raw ?? false, opts.json ?? false);
373
+ });
374
+ const feishuBitable = feishu
375
+ .command('bitable')
376
+ .description('Bitable (sheet) operations');
377
+ feishuBitable
378
+ .command('get')
379
+ .description('Get Bitable metadata')
380
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
381
+ .option('--json', 'Output as JSON')
382
+ .action(function () {
383
+ const opts = this.opts();
384
+ feishuBitableGetCommand(opts.sheetId, opts.json ?? false);
385
+ });
386
+ feishuBitable
387
+ .command('tables')
388
+ .description('Get tables list for a Bitable')
389
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
390
+ .option('--json', 'Output as JSON')
391
+ .action(function () {
392
+ const opts = this.opts();
393
+ feishuBitableTablesCommand(opts.sheetId, opts.json ?? false);
394
+ });
395
+ feishuBitable
396
+ .command('views')
397
+ .description('Get views list for a table')
398
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
399
+ .requiredOption('--table-id <table-id>', 'Table ID')
400
+ .option('--json', 'Output as JSON')
401
+ .action(function () {
402
+ const opts = this.opts();
403
+ feishuBitableViewsCommand(opts.sheetId, opts.tableId, opts.json ?? false);
404
+ });
405
+ feishuBitable
406
+ .command('view')
407
+ .description('Get details of a single view')
408
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
409
+ .requiredOption('--table-id <table-id>', 'Table ID')
410
+ .requiredOption('--view-id <view-id>', 'View ID')
411
+ .option('--json', 'Output as JSON')
412
+ .action(function () {
413
+ const opts = this.opts();
414
+ feishuBitableViewCommand(opts.sheetId, opts.tableId, opts.viewId, opts.json ?? false);
415
+ });
416
+ feishuBitable
417
+ .command('records')
418
+ .description('Get records from a table')
419
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
420
+ .requiredOption('--table-id <table-id>', 'Table ID')
421
+ .option('--json', 'Output as JSON')
422
+ .action(function () {
423
+ const opts = this.opts();
424
+ feishuBitableRecordsCommand(opts.sheetId, opts.tableId, opts.json ?? false);
425
+ });
426
+ feishuBitable
427
+ .command('record')
428
+ .description('Get a single record from a table')
429
+ .requiredOption('--sheet-id <sheet-id>', 'Sheet ID')
430
+ .requiredOption('--table-id <table-id>', 'Table ID')
431
+ .requiredOption('--record-id <record-id>', 'Record ID')
432
+ .option('--json', 'Output as JSON')
433
+ .action(function () {
434
+ const opts = this.opts();
435
+ feishuBitableRecordCommand(opts.sheetId, opts.tableId, opts.recordId, opts.json ?? false);
436
+ });
151
437
  program.parse();
152
438
  //# sourceMappingURL=cli.js.map