@scribe-platform/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/bin/scribe +4 -0
  4. package/dist/commands/build.d.ts +3 -0
  5. package/dist/commands/build.d.ts.map +1 -0
  6. package/dist/commands/build.js +14 -0
  7. package/dist/commands/build.js.map +1 -0
  8. package/dist/commands/content.d.ts +10 -0
  9. package/dist/commands/content.d.ts.map +1 -0
  10. package/dist/commands/content.js +110 -0
  11. package/dist/commands/content.js.map +1 -0
  12. package/dist/commands/login.d.ts +3 -0
  13. package/dist/commands/login.d.ts.map +1 -0
  14. package/dist/commands/login.js +16 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/commands/schema.d.ts +3 -0
  17. package/dist/commands/schema.d.ts.map +1 -0
  18. package/dist/commands/schema.js +26 -0
  19. package/dist/commands/schema.js.map +1 -0
  20. package/dist/commands/site.d.ts +3 -0
  21. package/dist/commands/site.d.ts.map +1 -0
  22. package/dist/commands/site.js +110 -0
  23. package/dist/commands/site.js.map +1 -0
  24. package/dist/commands/submission.d.ts +3 -0
  25. package/dist/commands/submission.d.ts.map +1 -0
  26. package/dist/commands/submission.js +52 -0
  27. package/dist/commands/submission.js.map +1 -0
  28. package/dist/index.d.ts +5 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +29 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/lib/cli-utils.d.ts +16 -0
  33. package/dist/lib/cli-utils.d.ts.map +1 -0
  34. package/dist/lib/cli-utils.js +52 -0
  35. package/dist/lib/cli-utils.js.map +1 -0
  36. package/dist/lib/client.d.ts +134 -0
  37. package/dist/lib/client.d.ts.map +1 -0
  38. package/dist/lib/client.js +108 -0
  39. package/dist/lib/client.js.map +1 -0
  40. package/dist/lib/config.d.ts +8 -0
  41. package/dist/lib/config.d.ts.map +1 -0
  42. package/dist/lib/config.js +23 -0
  43. package/dist/lib/config.js.map +1 -0
  44. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dave Weaver
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # @scribe-platform/cli
2
+
3
+ The `scribe` command line interface for [Scribe CMS](https://github.com/scribe-platform/scribe) —
4
+ provision sites, edit content, manage schemas, and triage form submissions from a terminal.
5
+
6
+ Scribe stores every site's content in its own GitHub repo as Markdown plus a
7
+ `.scribe.yml` schema. The CLI talks to a Scribe admin instance, which does the
8
+ GitHub work on your behalf.
9
+
10
+ ## Install
11
+
12
+ ```
13
+ npm install -g @scribe-platform/cli
14
+ ```
15
+
16
+ Requires Node.js 20 or newer.
17
+
18
+ ## Log in
19
+
20
+ You need an API key from a Scribe admin instance: sign in to the admin UI →
21
+ account menu → **API Tokens** → **New token**.
22
+
23
+ ```
24
+ scribe login --token <key>
25
+ ```
26
+
27
+ This writes `~/.scribe/config.json` (mode `600`); every other command reads it.
28
+ It defaults to the hosted admin at `https://scribe.appkit.net` — pass
29
+ `--api-url` (or set `SCRIBE_API_URL`) to point at a different one:
30
+
31
+ ```
32
+ scribe login --token <key> --api-url http://localhost:3000
33
+ ```
34
+
35
+ ## Commands
36
+
37
+ Run `scribe <group> --help` for the full options on any of these.
38
+
39
+ ### Sites
40
+
41
+ ```
42
+ scribe site list [--json]
43
+ scribe site add --slug <slug> [--domain <domain>] [--name <name>]
44
+ [--turnstile-key <key>] [--form-collection <name>]
45
+ scribe site update <slug> [--domain <domain>] [--turnstile-key <key>]
46
+ scribe site clone <slug> [directory]
47
+ scribe site delete <slug> [--yes]
48
+ ```
49
+
50
+ `site add` creates the GitHub repo, pushes the Astro starter template, and
51
+ registers the site with the admin in one step. `site clone` is a plain `git
52
+ clone` of the resulting repo, so you can work on the design locally.
53
+
54
+ `site delete` permanently removes the repo and every record of the site. It
55
+ cannot be undone, and prompts for confirmation unless you pass `--yes`.
56
+
57
+ ### Content
58
+
59
+ ```
60
+ scribe content list <site> [--collection <name>] [--json]
61
+ scribe content read <site> <path> [--json]
62
+ scribe content publish <site> <file>
63
+ scribe content delete <site> <path>
64
+ scribe content versions <site> <path> [--json]
65
+ scribe content revert <site> <path> --sha <commitSha>
66
+ ```
67
+
68
+ Paths are repo-relative (e.g. `content/posts/hello.md`). `content publish`
69
+ reads the identically-named file from your working directory and commits it to
70
+ that path.
71
+
72
+ ### Schema
73
+
74
+ ```
75
+ scribe schema add <site> <collection-name> [--path <path>]
76
+ scribe schema remove <site> <collection-name>
77
+ ```
78
+
79
+ `schema add` appends a bare collection stub to `.scribe.yml`. Fields are added
80
+ by hand-editing that file — it's ordinary YAML in the site's repo.
81
+
82
+ ### Form submissions
83
+
84
+ ```
85
+ scribe submission list <site> <collection> [--status <status>] [--json]
86
+ scribe submission update <site> <collection> <id> [--status <status>] [--notes <notes>]
87
+ ```
88
+
89
+ ### Builds
90
+
91
+ ```
92
+ scribe build trigger <site>
93
+ ```
94
+
95
+ Dispatches the site's build workflow. Debounced to once every five minutes.
96
+
97
+ ## Programmatic use
98
+
99
+ The API client and config helpers are exported for scripting:
100
+
101
+ ```js
102
+ import { ScribeClient, ScribeApiError } from '@scribe-platform/cli/client';
103
+ import { loadConfig } from '@scribe-platform/cli/config';
104
+
105
+ const config = loadConfig();
106
+ if (!config) throw new Error('Run `scribe login` first.');
107
+
108
+ const client = new ScribeClient(config);
109
+ const sites = await client.listSites();
110
+ ```
111
+
112
+ ## License
113
+
114
+ MIT
package/bin/scribe ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { createProgram } from '../dist/index.js';
3
+
4
+ createProgram().parseAsync(process.argv);
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerBuildCommands(program: Command): void;
3
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAc5D"}
@@ -0,0 +1,14 @@
1
+ import { requireClient, runAction } from '../lib/cli-utils.js';
2
+ export function registerBuildCommands(program) {
3
+ const build = program.command('build').description('Trigger a site rebuild');
4
+ build
5
+ .command('trigger')
6
+ .description('Dispatch the site\'s build workflow (debounced to once per 5 minutes)')
7
+ .argument('<site>', 'Site slug')
8
+ .action(runAction(async (site) => {
9
+ const client = requireClient();
10
+ const result = await client.triggerBuild(site);
11
+ console.log(result.dispatched ? 'Build dispatched.' : 'Skipped — a build was already dispatched within the last 5 minutes.');
12
+ }));
13
+ }
14
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAE7E,KAAK;SACF,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,uEAAuE,CAAC;SACpF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;SAC/B,MAAM,CACL,SAAS,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC/B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qEAAqE,CAAC,CAAC;IAC/H,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ interface FrontmatterFile {
3
+ frontmatter: Record<string, unknown>;
4
+ body?: string;
5
+ }
6
+ /** Best-effort local parse: YAML/JSON frontmatter delimited by "---", or a bare JSON/YAML object with no body. */
7
+ declare function parseLocalFile(raw: string): FrontmatterFile;
8
+ export declare function registerContentCommands(program: Command): void;
9
+ export { parseLocalFile };
10
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/commands/content.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID,kHAAkH;AAClH,iBAAS,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAOpD;AAmBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+F9D;AAGD,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,110 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { printResult, requireClient, runAction } from '../lib/cli-utils.js';
3
+ const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
4
+ /** Best-effort local parse: YAML/JSON frontmatter delimited by "---", or a bare JSON/YAML object with no body. */
5
+ function parseLocalFile(raw) {
6
+ const match = FRONTMATTER_RE.exec(raw);
7
+ if (match) {
8
+ const frontmatter = tryParseYamlOrJson(match[1]);
9
+ return { frontmatter, body: match[2] };
10
+ }
11
+ return { frontmatter: tryParseYamlOrJson(raw) };
12
+ }
13
+ function tryParseYamlOrJson(text) {
14
+ try {
15
+ return JSON.parse(text);
16
+ }
17
+ catch {
18
+ // Minimal fallback — real YAML parsing happens server-side against the
19
+ // collection's declared format; this local parse only needs to be good
20
+ // enough to round-trip `scribe content publish` for JSON/YAML files
21
+ // whose frontmatter is flat key: value pairs.
22
+ const result = {};
23
+ for (const line of text.split('\n')) {
24
+ const kv = /^([\w-]+):\s*(.*)$/.exec(line.trim());
25
+ if (kv)
26
+ result[kv[1]] = kv[2].replace(/^["']|["']$/g, '');
27
+ }
28
+ return result;
29
+ }
30
+ }
31
+ export function registerContentCommands(program) {
32
+ const content = program.command('content').description('Manage content items');
33
+ content
34
+ .command('list')
35
+ .description('List content items in one collection, or every collection if omitted')
36
+ .argument('<site>', 'Site slug')
37
+ .option('--collection <name>', 'Limit to one collection')
38
+ .option('--json', 'Output as JSON')
39
+ .action(runAction(async (site, opts) => {
40
+ const client = requireClient();
41
+ const items = await client.listContent(site, opts.collection);
42
+ printResult(items, opts.json);
43
+ }));
44
+ content
45
+ .command('read')
46
+ .description('Print a content item')
47
+ .argument('<site>', 'Site slug')
48
+ .argument('<path>', 'Repo-relative content path')
49
+ .option('--json', 'Output as JSON')
50
+ .action(runAction(async (site, path, opts) => {
51
+ const client = requireClient();
52
+ const item = await client.readContent(site, path);
53
+ printResult(item, opts.json);
54
+ }));
55
+ content
56
+ .command('publish')
57
+ .description('Publish a local file to the repo at the same relative path')
58
+ .argument('<site>', 'Site slug')
59
+ .argument('<file>', 'Repo-relative content path; read from the identically-named local file')
60
+ .action(runAction(async (site, file) => {
61
+ const client = requireClient();
62
+ const raw = readFileSync(file, 'utf-8');
63
+ const parsed = parseLocalFile(raw);
64
+ let sha;
65
+ try {
66
+ sha = (await client.readContent(site, file)).sha;
67
+ }
68
+ catch {
69
+ sha = undefined; // Doesn't exist yet — publish will create it.
70
+ }
71
+ const result = await client.publishContent(site, file, { frontmatter: parsed.frontmatter, body: parsed.body, sha });
72
+ console.log(`Published ${result.path} (${result.sha})`);
73
+ }));
74
+ content
75
+ .command('delete')
76
+ .description('Delete a content item and any images it references')
77
+ .argument('<site>', 'Site slug')
78
+ .argument('<path>', 'Repo-relative content path')
79
+ .action(runAction(async (site, path) => {
80
+ const client = requireClient();
81
+ const current = await client.readContent(site, path);
82
+ await client.deleteContent(site, path, current.sha);
83
+ console.log(`Deleted ${path}`);
84
+ }));
85
+ content
86
+ .command('versions')
87
+ .description('Show commit history for a content item')
88
+ .argument('<site>', 'Site slug')
89
+ .argument('<path>', 'Repo-relative content path')
90
+ .option('--json', 'Output as JSON')
91
+ .action(runAction(async (site, path, opts) => {
92
+ const client = requireClient();
93
+ const commits = await client.contentVersions(site, path);
94
+ printResult(commits, opts.json);
95
+ }));
96
+ content
97
+ .command('revert')
98
+ .description('Check out an old version of a content item as a new commit')
99
+ .argument('<site>', 'Site slug')
100
+ .argument('<path>', 'Repo-relative content path')
101
+ .requiredOption('--sha <commitSha>', 'Commit sha to revert to')
102
+ .action(runAction(async (site, path, opts) => {
103
+ const client = requireClient();
104
+ const result = await client.revertContent(site, path, opts.sha);
105
+ console.log(`Reverted ${result.path} to ${opts.sha} (new sha: ${result.sha})`);
106
+ }));
107
+ }
108
+ // Exported for tests exercising local frontmatter parsing.
109
+ export { parseLocalFile };
110
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/commands/content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerLoginCommand(program: Command): void;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAU3D"}
@@ -0,0 +1,16 @@
1
+ import { saveConfig } from '../lib/config.js';
2
+ // The hosted admin instance. Overridable per-machine with --api-url or
3
+ // SCRIBE_API_URL (both needed when pointing at a local dev/Docker admin).
4
+ const DEFAULT_API_URL = 'https://scribe.appkit.net';
5
+ export function registerLoginCommand(program) {
6
+ program
7
+ .command('login')
8
+ .description('Store an API key for authenticating future commands')
9
+ .requiredOption('--token <key>', 'API key (admin UI: account menu -> API Tokens -> New token)')
10
+ .option('--api-url <url>', 'Scribe admin API base URL', process.env.SCRIBE_API_URL ?? DEFAULT_API_URL)
11
+ .action((opts) => {
12
+ saveConfig({ token: opts.token, apiUrl: opts.apiUrl.replace(/\/+$/, '') });
13
+ console.log(`Logged in. Config saved to ~/.scribe/config.json (api: ${opts.apiUrl})`);
14
+ });
15
+ }
16
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,uEAAuE;AACvE,0EAA0E;AAC1E,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAEpD,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,qDAAqD,CAAC;SAClE,cAAc,CAAC,eAAe,EAAE,6DAA6D,CAAC;SAC9F,MAAM,CAAC,iBAAiB,EAAE,2BAA2B,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,eAAe,CAAC;SACrG,MAAM,CAAC,CAAC,IAAuC,EAAE,EAAE;QAClD,UAAU,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,0DAA0D,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSchemaCommands(program: Command): void;
3
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6B7D"}
@@ -0,0 +1,26 @@
1
+ import { requireClient, runAction } from '../lib/cli-utils.js';
2
+ export function registerSchemaCommands(program) {
3
+ const schema = program.command('schema').description('Manage a site\'s .scribe.yml collections');
4
+ schema
5
+ .command('add')
6
+ .description('Append a bare collection stub to .scribe.yml (add its fields separately)')
7
+ .argument('<site>', 'Site slug')
8
+ .argument('<collection-name>', 'New collection name')
9
+ .option('--path <path>', 'Repo path for the collection (defaults to content/<name>)')
10
+ .action(runAction(async (site, name, opts) => {
11
+ const client = requireClient();
12
+ await client.schemaAdd(site, name, opts.path);
13
+ console.log(`Added collection "${name}" to ${site}'s .scribe.yml`);
14
+ }));
15
+ schema
16
+ .command('remove')
17
+ .description('Remove a collection from .scribe.yml and delete its folder')
18
+ .argument('<site>', 'Site slug')
19
+ .argument('<collection-name>', 'Collection to remove')
20
+ .action(runAction(async (site, name) => {
21
+ const client = requireClient();
22
+ const result = await client.schemaRemove(site, name);
23
+ console.log(`Removed collection "${name}" from ${site}'s .scribe.yml (deleted ${result.deletedFiles} files)`);
24
+ }));
25
+ }
26
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0CAA0C,CAAC,CAAC;IAEjG,MAAM;SACH,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,0EAA0E,CAAC;SACvF,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;SAC/B,QAAQ,CAAC,mBAAmB,EAAE,qBAAqB,CAAC;SACpD,MAAM,CAAC,eAAe,EAAE,2DAA2D,CAAC;SACpF,MAAM,CACL,SAAS,CAAC,KAAK,EAAE,IAAY,EAAE,IAAY,EAAE,IAAuB,EAAE,EAAE;QACtE,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,QAAQ,IAAI,gBAAgB,CAAC,CAAC;IACrE,CAAC,CAAC,CACH,CAAC;IAEJ,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,4DAA4D,CAAC;SACzE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;SAC/B,QAAQ,CAAC,mBAAmB,EAAE,sBAAsB,CAAC;SACrD,MAAM,CACL,SAAS,CAAC,KAAK,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE;QAC7C,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,UAAU,IAAI,2BAA2B,MAAM,CAAC,YAAY,SAAS,CAAC,CAAC;IAChH,CAAC,CAAC,CACH,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSiteCommands(program: Command): void;
3
+ //# sourceMappingURL=site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../src/commands/site.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6H3D"}
@@ -0,0 +1,110 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { CliExit, printResult, requireClient, runAction } from '../lib/cli-utils.js';
4
+ export function registerSiteCommands(program) {
5
+ const site = program.command('site').description('Manage sites');
6
+ site
7
+ .command('list')
8
+ .description('List sites accessible to this API key')
9
+ .option('--json', 'Output as JSON')
10
+ .action(runAction(async (opts) => {
11
+ const client = requireClient();
12
+ const sites = await client.listSites();
13
+ printResult(sites, opts.json);
14
+ }));
15
+ site
16
+ .command('add')
17
+ .description('Provision a new site: create its GitHub repo, push a starter template, and register it')
18
+ .requiredOption('--slug <slug>', 'Site slug (also used as the repo name)')
19
+ .option('--domain <domain>', 'Site domain (defaults to the GitHub Pages host — set the real one later with `scribe site update --domain`)')
20
+ .option('--turnstile-key <key>', 'Cloudflare Turnstile site key (defaults to the server-configured shared widget)')
21
+ .option('--name <name>', 'Display name (defaults to the slug)')
22
+ .option('--form-collection <name>', 'Name for the default form/inbox collection (defaults to "inquiries")')
23
+ .action(runAction(async (opts) => {
24
+ const client = requireClient();
25
+ const result = await client.createSite({
26
+ slug: opts.slug,
27
+ domain: opts.domain,
28
+ turnstileSiteKey: opts.turnstileKey,
29
+ name: opts.name,
30
+ formCollectionName: opts.formCollection,
31
+ });
32
+ console.log(`Provisioned "${result.slug}" — repo: ${result.githubRepo}, form collection: ${result.formCollection}, domain: ${result.domain}`);
33
+ if (!result.turnstileSiteKey) {
34
+ console.log('No Turnstile key set — the contact form uses a placeholder until you run `scribe site update --turnstile-key`.');
35
+ }
36
+ }));
37
+ site
38
+ .command('update')
39
+ .description("Update a site's settings: its domain and/or Turnstile site key")
40
+ .argument('<slug>', 'Site slug')
41
+ .option('--turnstile-key <key>', 'Cloudflare Turnstile site key')
42
+ .option('--domain <domain>', "The site's public hostname, e.g. example.com — also synced to the Turnstile widget")
43
+ .action(runAction(async (slug, opts) => {
44
+ if (!opts.turnstileKey && !opts.domain) {
45
+ console.error('Nothing to update — pass --turnstile-key and/or --domain.');
46
+ process.exitCode = 1;
47
+ return;
48
+ }
49
+ const client = requireClient();
50
+ const result = await client.updateSite(slug, {
51
+ turnstileSiteKey: opts.turnstileKey,
52
+ domain: opts.domain,
53
+ });
54
+ console.log(`Updated "${slug}".`);
55
+ for (const warning of result.warnings ?? []) {
56
+ console.warn(`Warning: ${warning}`);
57
+ }
58
+ }));
59
+ site
60
+ .command('clone')
61
+ .description("Clone a site's GitHub repo locally, for hands-on design work in Astro before pushing changes back")
62
+ .argument('<slug>', 'Site slug')
63
+ .argument('[directory]', 'Destination directory (defaults to the site slug)')
64
+ .action(runAction(async (slug, directory) => {
65
+ const client = requireClient();
66
+ const sites = await client.listSites();
67
+ const site = sites.find((s) => s.slug === slug);
68
+ if (!site) {
69
+ console.error(`No site found with slug "${slug}" (or this key can't see it).`);
70
+ process.exitCode = 1;
71
+ throw new CliExit();
72
+ }
73
+ const url = `https://github.com/${site.githubOwner}/${site.githubRepo}.git`;
74
+ const args = directory ? ['clone', url, directory] : ['clone', url];
75
+ await new Promise((resolve, reject) => {
76
+ const child = spawn('git', args, { stdio: 'inherit' });
77
+ child.on('error', reject);
78
+ child.on('exit', (code) => {
79
+ if (code === 0)
80
+ resolve();
81
+ else
82
+ reject(new Error(`git clone exited with code ${code}`));
83
+ });
84
+ });
85
+ }));
86
+ site
87
+ .command('delete')
88
+ .description('Permanently delete a site: its GitHub repo and every record for it. Cannot be undone.')
89
+ .argument('<slug>', 'Site slug')
90
+ .option('--yes', 'Skip the interactive confirmation prompt')
91
+ .action(runAction(async (slug, opts) => {
92
+ if (!opts.yes) {
93
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
94
+ const answer = await rl.question(`This permanently deletes the GitHub repo and all Scribe data for "${slug}". Type the slug to confirm: `);
95
+ rl.close();
96
+ if (answer.trim() !== slug) {
97
+ console.error('Confirmation did not match — aborted.');
98
+ process.exitCode = 1;
99
+ return;
100
+ }
101
+ }
102
+ const client = requireClient();
103
+ const result = await client.deleteSite(slug);
104
+ console.log(`Deleted "${slug}".`);
105
+ for (const warning of result.warnings ?? []) {
106
+ console.warn(`Warning: ${warning}`);
107
+ }
108
+ }));
109
+ }
110
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.js","sourceRoot":"","sources":["../../src/commands/site.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerSubmissionCommands(program: Command): void;
3
+ //# sourceMappingURL=submission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../../src/commands/submission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA0DjE"}
@@ -0,0 +1,52 @@
1
+ import { printResult, requireClient, runAction } from '../lib/cli-utils.js';
2
+ export function registerSubmissionCommands(program) {
3
+ const submission = program.command('submission').description('Manage form submissions');
4
+ submission
5
+ .command('list')
6
+ .description('List submissions in a form collection')
7
+ .argument('<site>', 'Site slug')
8
+ .argument('<collection>', 'Form collection name')
9
+ .option('--status <status>', 'Filter by workflow status')
10
+ .option('--json', 'Output as JSON')
11
+ .action(runAction(async (site, collection, opts) => {
12
+ const client = requireClient();
13
+ const items = await client.listSubmissions(site, collection, opts.status);
14
+ printResult(items, opts.json);
15
+ }));
16
+ submission
17
+ .command('update')
18
+ .description('Update a submission\'s workflow status and/or notes')
19
+ .argument('<site>', 'Site slug')
20
+ .argument('<collection>', 'Form collection name')
21
+ .argument('<id>', 'Submission path or filename within the collection')
22
+ .option('--status <status>', 'New workflow status')
23
+ .option('--notes <notes>', 'Replace the internal notes field')
24
+ .action(runAction(async (site, collection, id, opts) => {
25
+ if (!opts.status && opts.notes === undefined) {
26
+ console.error('Provide --status and/or --notes');
27
+ process.exitCode = 1;
28
+ return;
29
+ }
30
+ const client = requireClient();
31
+ let path = id;
32
+ if (!id.includes('/')) {
33
+ const schema = await client.getSchema(site);
34
+ const collectionSchema = schema.collections.find((c) => c.name === collection);
35
+ if (!collectionSchema) {
36
+ console.error(`Collection "${collection}" not found in .scribe.yml`);
37
+ process.exitCode = 1;
38
+ return;
39
+ }
40
+ path = `${collectionSchema.path}/${id}`;
41
+ }
42
+ const current = await client.readContent(site, path).catch(() => null);
43
+ if (!current) {
44
+ console.error(`Submission not found: ${path}`);
45
+ process.exitCode = 1;
46
+ return;
47
+ }
48
+ const result = await client.updateSubmission(site, path, { status: opts.status, notes: opts.notes, sha: current.sha });
49
+ console.log(`Updated ${result.path} (${result.sha})`);
50
+ }));
51
+ }
52
+ //# sourceMappingURL=submission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/commands/submission.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Command } from 'commander';
2
+ export declare function createProgram(): Command;
3
+ export { ScribeClient, ScribeApiError } from './lib/client.js';
4
+ export { loadConfig, saveConfig } from './lib/config.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAepC,wBAAgB,aAAa,IAAI,OAAO,CAevC;AAED,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Command } from 'commander';
3
+ import { registerLoginCommand } from './commands/login.js';
4
+ import { registerSiteCommands } from './commands/site.js';
5
+ import { registerContentCommands } from './commands/content.js';
6
+ import { registerSubmissionCommands } from './commands/submission.js';
7
+ import { registerSchemaCommands } from './commands/schema.js';
8
+ import { registerBuildCommands } from './commands/build.js';
9
+ // Read from package.json at runtime rather than hardcoding: `../package.json`
10
+ // resolves to the package root from both `dist/index.js` (published) and
11
+ // `src/index.ts` (tests), so `scribe --version` can't drift from the release.
12
+ const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
13
+ export function createProgram() {
14
+ const program = new Command();
15
+ program
16
+ .name('scribe')
17
+ .description('Command-line interface for Scribe CMS')
18
+ .version(version);
19
+ registerLoginCommand(program);
20
+ registerSiteCommands(program);
21
+ registerContentCommands(program);
22
+ registerSubmissionCommands(program);
23
+ registerSchemaCommands(program);
24
+ registerBuildCommands(program);
25
+ return program;
26
+ }
27
+ export { ScribeClient, ScribeApiError } from './lib/client.js';
28
+ export { loadConfig, saveConfig } from './lib/config.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,8EAA8E;AAC9E,yEAAyE;AACzE,8EAA8E;AAC9E,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,KAAK,CAC5B,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAC5C,CAAC;AAEzB,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,QAAQ,CAAC;SACd,WAAW,CAAC,uCAAuC,CAAC;SACpD,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACpC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { ScribeClient } from './client.js';
2
+ /** Loads the stored config and builds a client, or exits with a clear message if not logged in. */
3
+ export declare function requireClient(): ScribeClient;
4
+ /** Thrown to unwind out of an action after already reporting the error — caught and swallowed at the top level. */
5
+ export declare class CliExit extends Error {
6
+ }
7
+ /**
8
+ * Wraps a command action so a `ScribeApiError` (4xx from the API — a user
9
+ * mistake) exits 1 with its message, and any other failure (network,
10
+ * bug) exits 2, per the delegation spec's exit-code contract. Generic over
11
+ * the action's argument tuple so commander's positional args + options
12
+ * object still reach the wrapped function untouched.
13
+ */
14
+ export declare function runAction<A extends unknown[]>(fn: (...args: A) => Promise<void>): (...args: A) => Promise<void>;
15
+ export declare function printResult(result: unknown, json: boolean | undefined): void;
16
+ //# sourceMappingURL=cli-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-utils.d.ts","sourceRoot":"","sources":["../../src/lib/cli-utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,mGAAmG;AACnG,wBAAgB,aAAa,IAAI,YAAY,CAQ5C;AAED,mHAAmH;AACnH,qBAAa,OAAQ,SAAQ,KAAK;CAAG;AAErC;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAe/G;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAU5E"}
@@ -0,0 +1,52 @@
1
+ import { loadConfig } from './config.js';
2
+ import { ScribeApiError, ScribeClient } from './client.js';
3
+ /** Loads the stored config and builds a client, or exits with a clear message if not logged in. */
4
+ export function requireClient() {
5
+ const config = loadConfig();
6
+ if (!config) {
7
+ console.error('Not logged in. Run `scribe login --token <key>` first.');
8
+ process.exitCode = 1;
9
+ throw new CliExit();
10
+ }
11
+ return new ScribeClient(config);
12
+ }
13
+ /** Thrown to unwind out of an action after already reporting the error — caught and swallowed at the top level. */
14
+ export class CliExit extends Error {
15
+ }
16
+ /**
17
+ * Wraps a command action so a `ScribeApiError` (4xx from the API — a user
18
+ * mistake) exits 1 with its message, and any other failure (network,
19
+ * bug) exits 2, per the delegation spec's exit-code contract. Generic over
20
+ * the action's argument tuple so commander's positional args + options
21
+ * object still reach the wrapped function untouched.
22
+ */
23
+ export function runAction(fn) {
24
+ return async (...args) => {
25
+ try {
26
+ await fn(...args);
27
+ }
28
+ catch (err) {
29
+ if (err instanceof CliExit)
30
+ return;
31
+ if (err instanceof ScribeApiError) {
32
+ console.error(`Error: ${err.message}`);
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ console.error('Unexpected error:', err instanceof Error ? err.message : err);
37
+ process.exitCode = 2;
38
+ }
39
+ };
40
+ }
41
+ export function printResult(result, json) {
42
+ if (json) {
43
+ console.log(JSON.stringify(result, null, 2));
44
+ return;
45
+ }
46
+ if (Array.isArray(result)) {
47
+ console.table(result);
48
+ return;
49
+ }
50
+ console.log(result);
51
+ }
52
+ //# sourceMappingURL=cli-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-utils.js","sourceRoot":"","sources":["../../src/lib/cli-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,mGAAmG;AACnG,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,MAAM,IAAI,OAAO,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED,mHAAmH;AACnH,MAAM,OAAO,OAAQ,SAAQ,KAAK;CAAG;AAErC;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAsB,EAAiC;IAC9E,OAAO,KAAK,EAAE,GAAG,IAAO,EAAE,EAAE;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,OAAO;gBAAE,OAAO;YACnC,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;gBAClC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAe,EAAE,IAAyB;IACpE,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,134 @@
1
+ export declare class ScribeApiError extends Error {
2
+ readonly status: number;
3
+ readonly body?: unknown | undefined;
4
+ constructor(message: string, status: number, body?: unknown | undefined);
5
+ }
6
+ export interface ScribeClientOptions {
7
+ apiUrl: string;
8
+ token: string;
9
+ }
10
+ export interface SiteSummary {
11
+ slug: string;
12
+ name: string;
13
+ domain: string;
14
+ githubOwner: string;
15
+ githubRepo: string;
16
+ }
17
+ export interface ContentItem {
18
+ collection: string;
19
+ path: string;
20
+ sha: string;
21
+ frontmatter: Record<string, unknown>;
22
+ }
23
+ export interface ContentDetail {
24
+ path: string;
25
+ sha: string;
26
+ frontmatter: Record<string, unknown>;
27
+ body?: string;
28
+ }
29
+ export interface CommitInfo {
30
+ sha: string;
31
+ message: string;
32
+ date: string;
33
+ author: string;
34
+ }
35
+ export interface SubmissionItem {
36
+ path: string;
37
+ sha: string;
38
+ fields: Record<string, unknown>;
39
+ submittedAt: number | null;
40
+ }
41
+ export interface SchemaCollection {
42
+ name: string;
43
+ path: string;
44
+ form?: boolean;
45
+ [key: string]: unknown;
46
+ }
47
+ export interface ScribeSchema {
48
+ collections: SchemaCollection[];
49
+ }
50
+ /**
51
+ * Thin HTTP client over the admin app's `/api/v1` surface, shared by the
52
+ * CLI and MCP server so the fetch/auth/error-mapping logic exists in one
53
+ * place. Every command/tool goes through this — no direct core or GitHub
54
+ * imports from either package.
55
+ */
56
+ export declare class ScribeClient {
57
+ private readonly options;
58
+ constructor(options: ScribeClientOptions);
59
+ private request;
60
+ whoami(): Promise<{
61
+ scope: 'read' | 'read-write';
62
+ siteSlugs: string[];
63
+ }>;
64
+ listSites(): Promise<SiteSummary[]>;
65
+ createSite(input: {
66
+ slug: string;
67
+ name?: string;
68
+ domain?: string;
69
+ turnstileSiteKey?: string;
70
+ formCollectionName?: string;
71
+ }): Promise<{
72
+ slug: string;
73
+ githubRepo: string;
74
+ formCollection: string;
75
+ domain: string;
76
+ turnstileSiteKey: string | null;
77
+ }>;
78
+ updateSite(site: string, input: {
79
+ turnstileSiteKey?: string;
80
+ domain?: string;
81
+ }): Promise<{
82
+ ok: true;
83
+ turnstileSiteKey?: string;
84
+ domain?: string;
85
+ warnings?: string[];
86
+ }>;
87
+ deleteSite(site: string): Promise<{
88
+ ok: true;
89
+ warnings?: string[];
90
+ }>;
91
+ listContent(site: string, collection?: string): Promise<ContentItem[]>;
92
+ readContent(site: string, path: string): Promise<ContentDetail>;
93
+ contentVersions(site: string, path: string): Promise<CommitInfo[]>;
94
+ publishContent(site: string, path: string, input: {
95
+ frontmatter: Record<string, unknown>;
96
+ body?: string;
97
+ sha?: string;
98
+ }): Promise<{
99
+ path: string;
100
+ sha: string;
101
+ message: string;
102
+ }>;
103
+ deleteContent(site: string, path: string, sha: string): Promise<{
104
+ ok: true;
105
+ deletedImages: number;
106
+ }>;
107
+ revertContent(site: string, path: string, sha: string): Promise<{
108
+ path: string;
109
+ sha: string;
110
+ }>;
111
+ listSubmissions(site: string, collection: string, status?: string): Promise<SubmissionItem[]>;
112
+ updateSubmission(site: string, path: string, input: {
113
+ status?: string;
114
+ notes?: string;
115
+ sha: string;
116
+ }): Promise<{
117
+ path: string;
118
+ sha: string;
119
+ fields: Record<string, unknown>;
120
+ }>;
121
+ getSchema(site: string): Promise<ScribeSchema>;
122
+ schemaAdd(site: string, name: string, path?: string): Promise<{
123
+ ok: true;
124
+ collection: string;
125
+ }>;
126
+ schemaRemove(site: string, name: string): Promise<{
127
+ ok: true;
128
+ deletedFiles: number;
129
+ }>;
130
+ triggerBuild(site: string): Promise<{
131
+ dispatched: boolean;
132
+ }>;
133
+ }
134
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ export class ScribeApiError extends Error {
2
+ status;
3
+ body;
4
+ constructor(message, status, body) {
5
+ super(message);
6
+ this.status = status;
7
+ this.body = body;
8
+ this.name = 'ScribeApiError';
9
+ }
10
+ }
11
+ /** Encodes a repo-relative path (e.g. "content/posts/hello.md") for use as a Next.js catch-all route segment. */
12
+ function encodePath(path) {
13
+ return path
14
+ .split('/')
15
+ .filter(Boolean)
16
+ .map(encodeURIComponent)
17
+ .join('/');
18
+ }
19
+ /**
20
+ * Thin HTTP client over the admin app's `/api/v1` surface, shared by the
21
+ * CLI and MCP server so the fetch/auth/error-mapping logic exists in one
22
+ * place. Every command/tool goes through this — no direct core or GitHub
23
+ * imports from either package.
24
+ */
25
+ export class ScribeClient {
26
+ options;
27
+ constructor(options) {
28
+ this.options = options;
29
+ }
30
+ async request(method, path, body) {
31
+ const res = await fetch(`${this.options.apiUrl}${path}`, {
32
+ method,
33
+ headers: {
34
+ Authorization: `Bearer ${this.options.token}`,
35
+ ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
36
+ },
37
+ body: body !== undefined ? JSON.stringify(body) : undefined,
38
+ });
39
+ const text = await res.text();
40
+ const data = text.length > 0 ? JSON.parse(text) : undefined;
41
+ if (!res.ok) {
42
+ const message = data && typeof data === 'object' && 'error' in data ? String(data.error) : res.statusText;
43
+ throw new ScribeApiError(message, res.status, data);
44
+ }
45
+ return data;
46
+ }
47
+ async whoami() {
48
+ return this.request('GET', '/api/v1/whoami');
49
+ }
50
+ async listSites() {
51
+ const { sites } = await this.request('GET', '/api/v1/sites');
52
+ return sites;
53
+ }
54
+ async createSite(input) {
55
+ return this.request('POST', '/api/v1/sites', input);
56
+ }
57
+ async updateSite(site, input) {
58
+ return this.request('PATCH', `/api/v1/sites/${encodeURIComponent(site)}`, input);
59
+ }
60
+ async deleteSite(site) {
61
+ return this.request('DELETE', `/api/v1/sites/${encodeURIComponent(site)}`);
62
+ }
63
+ async listContent(site, collection) {
64
+ const query = collection ? `?collection=${encodeURIComponent(collection)}` : '';
65
+ const { items } = await this.request('GET', `/api/v1/sites/${encodeURIComponent(site)}/content${query}`);
66
+ return items;
67
+ }
68
+ async readContent(site, path) {
69
+ return this.request('GET', `/api/v1/sites/${encodeURIComponent(site)}/content/${encodePath(path)}`);
70
+ }
71
+ async contentVersions(site, path) {
72
+ const { commits } = await this.request('GET', `/api/v1/sites/${encodeURIComponent(site)}/content/${encodePath(path)}?action=versions`);
73
+ return commits;
74
+ }
75
+ async publishContent(site, path, input) {
76
+ return this.request('PUT', `/api/v1/sites/${encodeURIComponent(site)}/content/${encodePath(path)}`, input);
77
+ }
78
+ async deleteContent(site, path, sha) {
79
+ return this.request('DELETE', `/api/v1/sites/${encodeURIComponent(site)}/content/${encodePath(path)}?sha=${encodeURIComponent(sha)}`);
80
+ }
81
+ async revertContent(site, path, sha) {
82
+ return this.request('POST', `/api/v1/sites/${encodeURIComponent(site)}/content/${encodePath(path)}?action=revert&sha=${encodeURIComponent(sha)}`);
83
+ }
84
+ async listSubmissions(site, collection, status) {
85
+ const query = new URLSearchParams({ collection, ...(status ? { status } : {}) });
86
+ const { items } = await this.request('GET', `/api/v1/sites/${encodeURIComponent(site)}/submissions?${query.toString()}`);
87
+ return items;
88
+ }
89
+ async updateSubmission(site, path, input) {
90
+ return this.request('PATCH', `/api/v1/sites/${encodeURIComponent(site)}/submissions/${encodePath(path)}`, input);
91
+ }
92
+ async getSchema(site) {
93
+ return this.request('GET', `/api/v1/sites/${encodeURIComponent(site)}/schema`);
94
+ }
95
+ async schemaAdd(site, name, path) {
96
+ return this.request('POST', `/api/v1/sites/${encodeURIComponent(site)}/schema/collections`, {
97
+ name,
98
+ path,
99
+ });
100
+ }
101
+ async schemaRemove(site, name) {
102
+ return this.request('DELETE', `/api/v1/sites/${encodeURIComponent(site)}/schema/collections/${encodeURIComponent(name)}`);
103
+ }
104
+ async triggerBuild(site) {
105
+ return this.request('POST', `/api/v1/sites/${encodeURIComponent(site)}/build`);
106
+ }
107
+ }
108
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface ScribeConfig {
2
+ token: string;
3
+ apiUrl: string;
4
+ }
5
+ export declare function loadConfig(): ScribeConfig | null;
6
+ export declare function saveConfig(config: ScribeConfig): void;
7
+ export declare function configPath(): string;
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,UAAU,IAAI,YAAY,GAAG,IAAI,CAOhD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAGrD;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -0,0 +1,23 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ const CONFIG_DIR = join(homedir(), '.scribe');
5
+ const CONFIG_PATH = join(CONFIG_DIR, 'config.json');
6
+ export function loadConfig() {
7
+ if (!existsSync(CONFIG_PATH))
8
+ return null;
9
+ try {
10
+ return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ }
16
+ export function saveConfig(config) {
17
+ mkdirSync(CONFIG_DIR, { recursive: true });
18
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 });
19
+ }
20
+ export function configPath() {
21
+ return CONFIG_PATH;
22
+ }
23
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAOjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAiB,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,WAAW,CAAC;AACrB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@scribe-platform/cli",
3
+ "version": "0.1.0",
4
+ "description": "Command-line interface for Scribe CMS \u2014 scaffold sites, edit content, and triage form submissions from the terminal",
5
+ "license": "MIT",
6
+ "author": "Dave Weaver",
7
+ "homepage": "https://github.com/scribe-platform/scribe/tree/main/packages/cli#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/scribe-platform/scribe.git",
11
+ "directory": "packages/cli"
12
+ },
13
+ "bugs": "https://github.com/scribe-platform/scribe/issues",
14
+ "keywords": [
15
+ "cms",
16
+ "scribe",
17
+ "astro",
18
+ "static-site",
19
+ "cli"
20
+ ],
21
+ "type": "module",
22
+ "bin": {
23
+ "scribe": "./bin/scribe"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": "./dist/index.js",
29
+ "./client": "./dist/lib/client.js",
30
+ "./config": "./dist/lib/config.js"
31
+ },
32
+ "files": [
33
+ "bin",
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
38
+ "engines": {
39
+ "node": ">=20"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc -p tsconfig.json",
46
+ "test": "NODE_OPTIONS=--experimental-vm-modules jest",
47
+ "lint": "tsc -p tsconfig.json --noEmit",
48
+ "prepublishOnly": "npm run build"
49
+ },
50
+ "dependencies": {
51
+ "commander": "^12.1.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/jest": "^29.5.13",
55
+ "@types/node": "^22.7.5",
56
+ "jest": "^29.7.0",
57
+ "ts-jest": "^29.2.5",
58
+ "typescript": "^5.6.3"
59
+ }
60
+ }