@fission-ai/openspec 0.20.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -140,6 +140,8 @@ These tools automatically read workflow instructions from `openspec/AGENTS.md`.
140
140
 
141
141
  #### Step 1: Install the CLI globally
142
142
 
143
+ **Option A: Using npm**
144
+
143
145
  ```bash
144
146
  npm install -g @fission-ai/openspec@latest
145
147
  ```
@@ -149,6 +151,39 @@ Verify installation:
149
151
  openspec --version
150
152
  ```
151
153
 
154
+ **Option B: Using Nix (NixOS and Nix package manager)**
155
+
156
+ Run OpenSpec directly without installation:
157
+ ```bash
158
+ nix run github:Fission-AI/OpenSpec -- init
159
+ ```
160
+
161
+ Or install to your profile:
162
+ ```bash
163
+ nix profile install github:Fission-AI/OpenSpec
164
+ ```
165
+
166
+ Or add to your development environment in `flake.nix`:
167
+ ```nix
168
+ {
169
+ inputs = {
170
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
171
+ openspec.url = "github:Fission-AI/OpenSpec";
172
+ };
173
+
174
+ outputs = { nixpkgs, openspec, ... }: {
175
+ devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell {
176
+ buildInputs = [ openspec.packages.x86_64-linux.default ];
177
+ };
178
+ };
179
+ }
180
+ ```
181
+
182
+ Verify installation:
183
+ ```bash
184
+ openspec --version
185
+ ```
186
+
152
187
  #### Step 2: Initialize OpenSpec in your project
153
188
 
154
189
  Navigate to your project directory:
package/dist/cli/index.js CHANGED
@@ -13,8 +13,10 @@ import { ChangeCommand } from '../commands/change.js';
13
13
  import { ValidateCommand } from '../commands/validate.js';
14
14
  import { ShowCommand } from '../commands/show.js';
15
15
  import { CompletionCommand } from '../commands/completion.js';
16
+ import { FeedbackCommand } from '../commands/feedback.js';
16
17
  import { registerConfigCommand } from '../commands/config.js';
17
18
  import { registerArtifactWorkflowCommands } from '../commands/artifact-workflow.js';
19
+ import { registerSchemaCommand } from '../commands/schema.js';
18
20
  import { maybeShowTelemetryNotice, trackCommand, shutdown } from '../telemetry/index.js';
19
21
  const program = new Command();
20
22
  const require = createRequire(import.meta.url);
@@ -229,6 +231,7 @@ program
229
231
  });
230
232
  registerSpecCommand(program);
231
233
  registerConfigCommand(program);
234
+ registerSchemaCommand(program);
232
235
  // Top-level validate command
233
236
  program
234
237
  .command('validate [item-name]')
@@ -279,6 +282,22 @@ program
279
282
  process.exit(1);
280
283
  }
281
284
  });
285
+ // Feedback command
286
+ program
287
+ .command('feedback <message>')
288
+ .description('Submit feedback about OpenSpec')
289
+ .option('--body <text>', 'Detailed description for the feedback')
290
+ .action(async (message, options) => {
291
+ try {
292
+ const feedbackCommand = new FeedbackCommand();
293
+ await feedbackCommand.execute(message, options);
294
+ }
295
+ catch (error) {
296
+ console.log();
297
+ ora().fail(`Error: ${error.message}`);
298
+ process.exit(1);
299
+ }
300
+ });
282
301
  // Completion command with subcommands
283
302
  const completionCmd = program
284
303
  .command('completion')
@@ -16,6 +16,7 @@ import { loadChangeContext, formatChangeStatus, generateInstructions, listSchema
16
16
  import { createChange, validateChangeName } from '../utils/change-utils.js';
17
17
  import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxVerifyCommandTemplate } from '../core/templates/skill-templates.js';
18
18
  import { FileSystemUtils } from '../utils/file-system.js';
19
+ import { promptForConfig, serializeConfig, isExitPromptError } from '../core/config-prompts.js';
19
20
  const DEFAULT_SCHEMA = 'spec-driven';
20
21
  /**
21
22
  * Checks if color output is disabled via NO_COLOR env or --no-color flag.
@@ -97,11 +98,14 @@ async function validateChangeExists(changeName, projectRoot) {
97
98
  }
98
99
  /**
99
100
  * Validates that a schema exists and returns available schemas if not.
101
+ *
102
+ * @param schemaName - The schema name to validate
103
+ * @param projectRoot - Optional project root for project-local schema resolution
100
104
  */
101
- function validateSchemaExists(schemaName) {
102
- const schemaDir = getSchemaDir(schemaName);
105
+ function validateSchemaExists(schemaName, projectRoot) {
106
+ const schemaDir = getSchemaDir(schemaName, projectRoot);
103
107
  if (!schemaDir) {
104
- const availableSchemas = listSchemas();
108
+ const availableSchemas = listSchemas(projectRoot);
105
109
  throw new Error(`Schema '${schemaName}' not found. Available schemas:\n ${availableSchemas.join('\n ')}`);
106
110
  }
107
111
  return schemaName;
@@ -113,7 +117,7 @@ async function statusCommand(options) {
113
117
  const changeName = await validateChangeExists(options.change, projectRoot);
114
118
  // Validate schema if explicitly provided
115
119
  if (options.schema) {
116
- validateSchemaExists(options.schema);
120
+ validateSchemaExists(options.schema, projectRoot);
117
121
  }
118
122
  // loadChangeContext will auto-detect schema from metadata if not provided
119
123
  const context = loadChangeContext(projectRoot, changeName, options.schema);
@@ -158,7 +162,7 @@ async function instructionsCommand(artifactId, options) {
158
162
  const changeName = await validateChangeExists(options.change, projectRoot);
159
163
  // Validate schema if explicitly provided
160
164
  if (options.schema) {
161
- validateSchemaExists(options.schema);
165
+ validateSchemaExists(options.schema, projectRoot);
162
166
  }
163
167
  // loadChangeContext will auto-detect schema from metadata if not provided
164
168
  const context = loadChangeContext(projectRoot, changeName, options.schema);
@@ -173,7 +177,7 @@ async function instructionsCommand(artifactId, options) {
173
177
  const validIds = context.graph.getAllArtifacts().map((a) => a.id);
174
178
  throw new Error(`Artifact '${artifactId}' not found in schema '${context.schemaName}'. Valid artifacts:\n ${validIds.join('\n ')}`);
175
179
  }
176
- const instructions = generateInstructions(context, artifactId);
180
+ const instructions = generateInstructions(context, artifactId, projectRoot);
177
181
  const isBlocked = instructions.dependencies.some((d) => !d.done);
178
182
  spinner.stop();
179
183
  if (options.json) {
@@ -433,7 +437,7 @@ async function applyInstructionsCommand(options) {
433
437
  const changeName = await validateChangeExists(options.change, projectRoot);
434
438
  // Validate schema if explicitly provided
435
439
  if (options.schema) {
436
- validateSchemaExists(options.schema);
440
+ validateSchemaExists(options.schema, projectRoot);
437
441
  }
438
442
  // generateApplyInstructions uses loadChangeContext which auto-detects schema
439
443
  const instructions = await generateApplyInstructions(projectRoot, changeName, options.schema);
@@ -498,18 +502,29 @@ function printApplyInstructionsText(instructions) {
498
502
  async function templatesCommand(options) {
499
503
  const spinner = ora('Loading templates...').start();
500
504
  try {
501
- const schemaName = validateSchemaExists(options.schema ?? DEFAULT_SCHEMA);
502
- const schema = resolveSchema(schemaName);
505
+ const projectRoot = process.cwd();
506
+ const schemaName = validateSchemaExists(options.schema ?? DEFAULT_SCHEMA, projectRoot);
507
+ const schema = resolveSchema(schemaName, projectRoot);
503
508
  const graph = ArtifactGraph.fromSchema(schema);
504
- const schemaDir = getSchemaDir(schemaName);
505
- // Determine if this is a user override or package built-in
506
- const { getUserSchemasDir } = await import('../core/artifact-graph/resolver.js');
509
+ const schemaDir = getSchemaDir(schemaName, projectRoot);
510
+ // Determine the source (project, user, or package)
511
+ const { getUserSchemasDir, getProjectSchemasDir, } = await import('../core/artifact-graph/resolver.js');
512
+ const projectSchemasDir = getProjectSchemasDir(projectRoot);
507
513
  const userSchemasDir = getUserSchemasDir();
508
- const isUserOverride = schemaDir.startsWith(userSchemasDir);
514
+ let source;
515
+ if (schemaDir.startsWith(projectSchemasDir)) {
516
+ source = 'project';
517
+ }
518
+ else if (schemaDir.startsWith(userSchemasDir)) {
519
+ source = 'user';
520
+ }
521
+ else {
522
+ source = 'package';
523
+ }
509
524
  const templates = graph.getAllArtifacts().map((artifact) => ({
510
525
  artifactId: artifact.id,
511
526
  templatePath: path.join(schemaDir, 'templates', artifact.template),
512
- source: isUserOverride ? 'user' : 'package',
527
+ source,
513
528
  }));
514
529
  spinner.stop();
515
530
  if (options.json) {
@@ -521,7 +536,7 @@ async function templatesCommand(options) {
521
536
  return;
522
537
  }
523
538
  console.log(`Schema: ${schemaName}`);
524
- console.log(`Source: ${isUserOverride ? 'user override' : 'package built-in'}`);
539
+ console.log(`Source: ${source}`);
525
540
  console.log();
526
541
  for (const t of templates) {
527
542
  console.log(`${t.artifactId}:`);
@@ -541,15 +556,15 @@ async function newChangeCommand(name, options) {
541
556
  if (!validation.valid) {
542
557
  throw new Error(validation.error);
543
558
  }
559
+ const projectRoot = process.cwd();
544
560
  // Validate schema if provided
545
561
  if (options.schema) {
546
- validateSchemaExists(options.schema);
562
+ validateSchemaExists(options.schema, projectRoot);
547
563
  }
548
564
  const schemaDisplay = options.schema ? ` with schema '${options.schema}'` : '';
549
565
  const spinner = ora(`Creating change '${name}'${schemaDisplay}...`).start();
550
566
  try {
551
- const projectRoot = process.cwd();
552
- await createChange(projectRoot, name, { schema: options.schema });
567
+ const result = await createChange(projectRoot, name, { schema: options.schema });
553
568
  // If description provided, create README.md with description
554
569
  if (options.description) {
555
570
  const { promises: fs } = await import('fs');
@@ -557,8 +572,7 @@ async function newChangeCommand(name, options) {
557
572
  const readmePath = path.join(changeDir, 'README.md');
558
573
  await fs.writeFile(readmePath, `# ${name}\n\n${options.description}\n`, 'utf-8');
559
574
  }
560
- const schemaUsed = options.schema ?? DEFAULT_SCHEMA;
561
- spinner.succeed(`Created change '${name}' at openspec/changes/${name}/ (schema: ${schemaUsed})`);
575
+ spinner.succeed(`Created change '${name}' at openspec/changes/${name}/ (schema: ${result.schema})`);
562
576
  }
563
577
  catch (error) {
564
578
  spinner.fail(`Failed to create change '${name}'`);
@@ -667,6 +681,118 @@ ${template.content}
667
681
  console.log(chalk.green(' ✓ ' + file));
668
682
  }
669
683
  console.log();
684
+ // Config creation section
685
+ console.log('━'.repeat(70));
686
+ console.log();
687
+ console.log(chalk.bold('📋 Project Configuration (Optional)'));
688
+ console.log();
689
+ console.log('Configure project defaults for OpenSpec workflows.');
690
+ console.log();
691
+ // Check if config already exists
692
+ const configPath = path.join(projectRoot, 'openspec', 'config.yaml');
693
+ const configYmlPath = path.join(projectRoot, 'openspec', 'config.yml');
694
+ const configExists = fs.existsSync(configPath) || fs.existsSync(configYmlPath);
695
+ if (configExists) {
696
+ // Config already exists, skip creation
697
+ console.log(chalk.blue('ℹ️ openspec/config.yaml already exists. Skipping config creation.'));
698
+ console.log();
699
+ console.log(' To update config, edit openspec/config.yaml manually or:');
700
+ console.log(' 1. Delete openspec/config.yaml');
701
+ console.log(' 2. Run openspec artifact-experimental-setup again');
702
+ console.log();
703
+ }
704
+ else if (!process.stdin.isTTY) {
705
+ // Non-interactive mode (CI, automation, piped input)
706
+ console.log(chalk.blue('ℹ️ Skipping config prompts (non-interactive mode)'));
707
+ console.log();
708
+ console.log(' To create config manually, add openspec/config.yaml with:');
709
+ console.log(chalk.dim(' schema: spec-driven'));
710
+ console.log();
711
+ }
712
+ else {
713
+ // Prompt for config creation
714
+ try {
715
+ const configResult = await promptForConfig(projectRoot);
716
+ if (configResult.createConfig && configResult.schema) {
717
+ // Build config object
718
+ const config = {
719
+ schema: configResult.schema,
720
+ context: configResult.context,
721
+ rules: configResult.rules,
722
+ };
723
+ // Serialize to YAML
724
+ const yamlContent = serializeConfig(config);
725
+ // Write config file
726
+ try {
727
+ await FileSystemUtils.writeFile(configPath, yamlContent);
728
+ console.log();
729
+ console.log(chalk.green('✓ Created openspec/config.yaml'));
730
+ console.log();
731
+ console.log('━'.repeat(70));
732
+ console.log();
733
+ console.log(chalk.bold('📖 Config created at: openspec/config.yaml'));
734
+ // Display summary
735
+ const contextLines = config.context ? config.context.split('\n').length : 0;
736
+ const rulesCount = config.rules ? Object.keys(config.rules).length : 0;
737
+ console.log(` • Default schema: ${chalk.cyan(config.schema)}`);
738
+ if (contextLines > 0) {
739
+ console.log(` • Project context: ${chalk.cyan(`Added (${contextLines} lines)`)}`);
740
+ }
741
+ if (rulesCount > 0) {
742
+ console.log(` • Rules: ${chalk.cyan(`${rulesCount} artifact${rulesCount > 1 ? 's' : ''} configured`)}`);
743
+ }
744
+ console.log();
745
+ // Usage examples
746
+ console.log(chalk.bold('Usage:'));
747
+ console.log(' • New changes automatically use this schema');
748
+ console.log(' • Context injected into all artifact instructions');
749
+ console.log(' • Rules applied to matching artifacts');
750
+ console.log();
751
+ // Git commit suggestion
752
+ console.log(chalk.bold('To share with team:'));
753
+ console.log(chalk.dim(' git add openspec/config.yaml .claude/'));
754
+ console.log(chalk.dim(' git commit -m "Setup OpenSpec experimental workflow with project config"'));
755
+ console.log();
756
+ }
757
+ catch (writeError) {
758
+ // Handle file write errors
759
+ console.error();
760
+ console.error(chalk.red('✗ Failed to write openspec/config.yaml'));
761
+ console.error(chalk.dim(` ${writeError.message}`));
762
+ console.error();
763
+ console.error('Fallback: Create config manually:');
764
+ console.error(chalk.dim(' 1. Create openspec/config.yaml'));
765
+ console.error(chalk.dim(' 2. Copy the following content:'));
766
+ console.error();
767
+ console.error(chalk.dim(yamlContent));
768
+ console.error();
769
+ }
770
+ }
771
+ else {
772
+ // User chose not to create config
773
+ console.log();
774
+ console.log(chalk.blue('ℹ️ Skipped config creation.'));
775
+ console.log(' You can create openspec/config.yaml manually later.');
776
+ console.log();
777
+ }
778
+ }
779
+ catch (promptError) {
780
+ if (isExitPromptError(promptError)) {
781
+ // User cancelled (Ctrl+C)
782
+ console.log();
783
+ console.log(chalk.blue('ℹ️ Config creation cancelled'));
784
+ console.log(' Skills and commands already created');
785
+ console.log(' Run setup again to create config later');
786
+ console.log();
787
+ }
788
+ else {
789
+ // Unexpected error
790
+ throw promptError;
791
+ }
792
+ }
793
+ }
794
+ console.log('━'.repeat(70));
795
+ console.log();
670
796
  console.log(chalk.bold('📖 Usage:'));
671
797
  console.log();
672
798
  console.log(' ' + chalk.cyan('Skills') + ' work automatically in compatible editors:');
@@ -699,7 +825,8 @@ ${template.content}
699
825
  }
700
826
  }
701
827
  async function schemasCommand(options) {
702
- const schemas = listSchemasWithInfo();
828
+ const projectRoot = process.cwd();
829
+ const schemas = listSchemasWithInfo(projectRoot);
703
830
  if (options.json) {
704
831
  console.log(JSON.stringify(schemas, null, 2));
705
832
  return;
@@ -707,7 +834,13 @@ async function schemasCommand(options) {
707
834
  console.log('Available schemas:');
708
835
  console.log();
709
836
  for (const schema of schemas) {
710
- const sourceLabel = schema.source === 'user' ? chalk.dim(' (user override)') : '';
837
+ let sourceLabel = '';
838
+ if (schema.source === 'project') {
839
+ sourceLabel = chalk.cyan(' (project)');
840
+ }
841
+ else if (schema.source === 'user') {
842
+ sourceLabel = chalk.dim(' (user override)');
843
+ }
711
844
  console.log(` ${chalk.bold(schema.name)}${sourceLabel}`);
712
845
  console.log(` ${schema.description}`);
713
846
  console.log(` Artifacts: ${schema.artifacts.join(' → ')}`);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Feedback command implementation
3
+ */
4
+ export declare class FeedbackCommand {
5
+ execute(message: string, options?: {
6
+ body?: string;
7
+ }): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1,183 @@
1
+ import { execSync, execFileSync } from 'child_process';
2
+ import { createRequire } from 'module';
3
+ import os from 'os';
4
+ const require = createRequire(import.meta.url);
5
+ /**
6
+ * Check if gh CLI is installed and available in PATH
7
+ * Uses platform-appropriate command: 'where' on Windows, 'which' on Unix/macOS
8
+ */
9
+ function isGhInstalled() {
10
+ try {
11
+ const command = process.platform === 'win32' ? 'where gh' : 'which gh';
12
+ execSync(command, { stdio: 'pipe' });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Check if gh CLI is authenticated
21
+ */
22
+ function isGhAuthenticated() {
23
+ try {
24
+ execSync('gh auth status', { stdio: 'pipe' });
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Get OpenSpec version from package.json
33
+ */
34
+ function getVersion() {
35
+ try {
36
+ const { version } = require('../../package.json');
37
+ return version;
38
+ }
39
+ catch {
40
+ return 'unknown';
41
+ }
42
+ }
43
+ /**
44
+ * Get platform name
45
+ */
46
+ function getPlatform() {
47
+ return os.platform();
48
+ }
49
+ /**
50
+ * Get current timestamp in ISO format
51
+ */
52
+ function getTimestamp() {
53
+ return new Date().toISOString();
54
+ }
55
+ /**
56
+ * Generate metadata footer for feedback
57
+ */
58
+ function generateMetadata() {
59
+ const version = getVersion();
60
+ const platform = getPlatform();
61
+ const timestamp = getTimestamp();
62
+ return `---
63
+ Submitted via OpenSpec CLI
64
+ - Version: ${version}
65
+ - Platform: ${platform}
66
+ - Timestamp: ${timestamp}`;
67
+ }
68
+ /**
69
+ * Format the feedback title
70
+ */
71
+ function formatTitle(message) {
72
+ return `Feedback: ${message}`;
73
+ }
74
+ /**
75
+ * Format the full feedback body
76
+ */
77
+ function formatBody(bodyText) {
78
+ const parts = [];
79
+ if (bodyText) {
80
+ parts.push(bodyText);
81
+ parts.push(''); // Empty line before metadata
82
+ }
83
+ parts.push(generateMetadata());
84
+ return parts.join('\n');
85
+ }
86
+ /**
87
+ * Generate a pre-filled GitHub issue URL for manual submission
88
+ */
89
+ function generateManualSubmissionUrl(title, body) {
90
+ const repo = 'Fission-AI/OpenSpec';
91
+ const encodedTitle = encodeURIComponent(title);
92
+ const encodedBody = encodeURIComponent(body);
93
+ const encodedLabels = encodeURIComponent('feedback');
94
+ return `https://github.com/${repo}/issues/new?title=${encodedTitle}&body=${encodedBody}&labels=${encodedLabels}`;
95
+ }
96
+ /**
97
+ * Display formatted feedback content for manual submission
98
+ */
99
+ function displayFormattedFeedback(title, body) {
100
+ console.log('\n--- FORMATTED FEEDBACK ---');
101
+ console.log(`Title: ${title}`);
102
+ console.log(`Labels: feedback`);
103
+ console.log('\nBody:');
104
+ console.log(body);
105
+ console.log('--- END FEEDBACK ---\n');
106
+ }
107
+ /**
108
+ * Submit feedback via gh CLI
109
+ * Uses execFileSync to prevent shell injection vulnerabilities
110
+ */
111
+ function submitViaGhCli(title, body) {
112
+ try {
113
+ const result = execFileSync('gh', [
114
+ 'issue',
115
+ 'create',
116
+ '--repo',
117
+ 'Fission-AI/OpenSpec',
118
+ '--title',
119
+ title,
120
+ '--body',
121
+ body,
122
+ '--label',
123
+ 'feedback',
124
+ ], { encoding: 'utf-8', stdio: 'pipe' });
125
+ const issueUrl = result.trim();
126
+ console.log(`\n✓ Feedback submitted successfully!`);
127
+ console.log(`Issue URL: ${issueUrl}\n`);
128
+ }
129
+ catch (error) {
130
+ // Display the error output from gh CLI
131
+ if (error.stderr) {
132
+ console.error(error.stderr.toString());
133
+ }
134
+ else if (error.message) {
135
+ console.error(error.message);
136
+ }
137
+ // Exit with the same code as gh CLI
138
+ process.exit(error.status ?? 1);
139
+ }
140
+ }
141
+ /**
142
+ * Handle fallback when gh CLI is not available or not authenticated
143
+ */
144
+ function handleFallback(title, body, reason) {
145
+ if (reason === 'missing') {
146
+ console.log('⚠️ GitHub CLI not found. Manual submission required.');
147
+ }
148
+ else {
149
+ console.log('⚠️ GitHub authentication required. Manual submission required.');
150
+ }
151
+ displayFormattedFeedback(title, body);
152
+ const manualUrl = generateManualSubmissionUrl(title, body);
153
+ console.log('Please submit your feedback manually:');
154
+ console.log(manualUrl);
155
+ if (reason === 'unauthenticated') {
156
+ console.log('\nTo auto-submit in the future: gh auth login');
157
+ }
158
+ // Exit with success code (fallback is successful)
159
+ process.exit(0);
160
+ }
161
+ /**
162
+ * Feedback command implementation
163
+ */
164
+ export class FeedbackCommand {
165
+ async execute(message, options) {
166
+ // Format title and body once for all code paths
167
+ const title = formatTitle(message);
168
+ const body = formatBody(options?.body);
169
+ // Check if gh CLI is installed
170
+ if (!isGhInstalled()) {
171
+ handleFallback(title, body, 'missing');
172
+ return;
173
+ }
174
+ // Check if gh CLI is authenticated
175
+ if (!isGhAuthenticated()) {
176
+ handleFallback(title, body, 'unauthenticated');
177
+ return;
178
+ }
179
+ // Submit via gh CLI
180
+ submitViaGhCli(title, body);
181
+ }
182
+ }
183
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the schema command and all its subcommands.
4
+ */
5
+ export declare function registerSchemaCommand(program: Command): void;
6
+ //# sourceMappingURL=schema.d.ts.map