@hitslop/shots 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 (151) hide show
  1. package/SKILL.md +536 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +113 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/auth.d.ts +7 -0
  7. package/dist/commands/auth.d.ts.map +1 -0
  8. package/dist/commands/auth.js +106 -0
  9. package/dist/commands/auth.js.map +1 -0
  10. package/dist/commands/crop.d.ts +5 -0
  11. package/dist/commands/crop.d.ts.map +1 -0
  12. package/dist/commands/crop.js +32 -0
  13. package/dist/commands/crop.js.map +1 -0
  14. package/dist/commands/default.d.ts +2 -0
  15. package/dist/commands/default.d.ts.map +1 -0
  16. package/dist/commands/default.js +142 -0
  17. package/dist/commands/default.js.map +1 -0
  18. package/dist/commands/feedback.d.ts +2 -0
  19. package/dist/commands/feedback.d.ts.map +1 -0
  20. package/dist/commands/feedback.js +6 -0
  21. package/dist/commands/feedback.js.map +1 -0
  22. package/dist/commands/generate.d.ts +3 -0
  23. package/dist/commands/generate.d.ts.map +1 -0
  24. package/dist/commands/generate.js +5 -0
  25. package/dist/commands/generate.js.map +1 -0
  26. package/dist/commands/init.d.ts +2 -0
  27. package/dist/commands/init.d.ts.map +1 -0
  28. package/dist/commands/init.js +5 -0
  29. package/dist/commands/init.js.map +1 -0
  30. package/dist/commands/install.d.ts +2 -0
  31. package/dist/commands/install.d.ts.map +1 -0
  32. package/dist/commands/install.js +13 -0
  33. package/dist/commands/install.js.map +1 -0
  34. package/dist/commands/scrape.d.ts +5 -0
  35. package/dist/commands/scrape.d.ts.map +1 -0
  36. package/dist/commands/scrape.js +5 -0
  37. package/dist/commands/scrape.js.map +1 -0
  38. package/dist/commands/studio.d.ts +7 -0
  39. package/dist/commands/studio.d.ts.map +1 -0
  40. package/dist/commands/studio.js +351 -0
  41. package/dist/commands/studio.js.map +1 -0
  42. package/dist/commands/styles.d.ts +2 -0
  43. package/dist/commands/styles.d.ts.map +1 -0
  44. package/dist/commands/styles.js +25 -0
  45. package/dist/commands/styles.js.map +1 -0
  46. package/dist/commands/view.d.ts +2 -0
  47. package/dist/commands/view.d.ts.map +1 -0
  48. package/dist/commands/view.js +25 -0
  49. package/dist/commands/view.js.map +1 -0
  50. package/dist/core/crop-pipeline.d.ts +28 -0
  51. package/dist/core/crop-pipeline.d.ts.map +1 -0
  52. package/dist/core/crop-pipeline.js +82 -0
  53. package/dist/core/crop-pipeline.js.map +1 -0
  54. package/dist/core/generate.d.ts +20 -0
  55. package/dist/core/generate.d.ts.map +1 -0
  56. package/dist/core/generate.js +388 -0
  57. package/dist/core/generate.js.map +1 -0
  58. package/dist/core/init.d.ts +3 -0
  59. package/dist/core/init.d.ts.map +1 -0
  60. package/dist/core/init.js +77 -0
  61. package/dist/core/init.js.map +1 -0
  62. package/dist/core/mock-generator.d.ts +5 -0
  63. package/dist/core/mock-generator.d.ts.map +1 -0
  64. package/dist/core/mock-generator.js +42 -0
  65. package/dist/core/mock-generator.js.map +1 -0
  66. package/dist/core/prompt-builder.d.ts +15 -0
  67. package/dist/core/prompt-builder.d.ts.map +1 -0
  68. package/dist/core/prompt-builder.js +195 -0
  69. package/dist/core/prompt-builder.js.map +1 -0
  70. package/dist/core/providers/fal.d.ts +3 -0
  71. package/dist/core/providers/fal.d.ts.map +1 -0
  72. package/dist/core/providers/fal.js +53 -0
  73. package/dist/core/providers/fal.js.map +1 -0
  74. package/dist/core/providers/index.d.ts +3 -0
  75. package/dist/core/providers/index.d.ts.map +1 -0
  76. package/dist/core/providers/index.js +2 -0
  77. package/dist/core/providers/index.js.map +1 -0
  78. package/dist/core/providers/managed.d.ts +3 -0
  79. package/dist/core/providers/managed.d.ts.map +1 -0
  80. package/dist/core/providers/managed.js +132 -0
  81. package/dist/core/providers/managed.js.map +1 -0
  82. package/dist/core/providers/openai.d.ts +3 -0
  83. package/dist/core/providers/openai.d.ts.map +1 -0
  84. package/dist/core/providers/openai.js +40 -0
  85. package/dist/core/providers/openai.js.map +1 -0
  86. package/dist/core/providers/replicate.d.ts +3 -0
  87. package/dist/core/providers/replicate.d.ts.map +1 -0
  88. package/dist/core/providers/replicate.js +87 -0
  89. package/dist/core/providers/replicate.js.map +1 -0
  90. package/dist/core/providers/resolve.d.ts +3 -0
  91. package/dist/core/providers/resolve.d.ts.map +1 -0
  92. package/dist/core/providers/resolve.js +41 -0
  93. package/dist/core/providers/resolve.js.map +1 -0
  94. package/dist/core/providers/types.d.ts +29 -0
  95. package/dist/core/providers/types.d.ts.map +1 -0
  96. package/dist/core/providers/types.js +2 -0
  97. package/dist/core/providers/types.js.map +1 -0
  98. package/dist/core/scraper.d.ts +22 -0
  99. package/dist/core/scraper.d.ts.map +1 -0
  100. package/dist/core/scraper.js +138 -0
  101. package/dist/core/scraper.js.map +1 -0
  102. package/dist/core/walkthrough.d.ts +10 -0
  103. package/dist/core/walkthrough.d.ts.map +1 -0
  104. package/dist/core/walkthrough.js +116 -0
  105. package/dist/core/walkthrough.js.map +1 -0
  106. package/dist/schema/config.d.ts +45 -0
  107. package/dist/schema/config.d.ts.map +1 -0
  108. package/dist/schema/config.js +36 -0
  109. package/dist/schema/config.js.map +1 -0
  110. package/dist/schema/manifest.d.ts +43 -0
  111. package/dist/schema/manifest.d.ts.map +1 -0
  112. package/dist/schema/manifest.js +5 -0
  113. package/dist/schema/manifest.js.map +1 -0
  114. package/dist/schema/style-meta.d.ts +8 -0
  115. package/dist/schema/style-meta.d.ts.map +1 -0
  116. package/dist/schema/style-meta.js +2 -0
  117. package/dist/schema/style-meta.js.map +1 -0
  118. package/dist/styles/installer.d.ts +2 -0
  119. package/dist/styles/installer.d.ts.map +1 -0
  120. package/dist/styles/installer.js +43 -0
  121. package/dist/styles/installer.js.map +1 -0
  122. package/dist/styles/registry.d.ts +20 -0
  123. package/dist/styles/registry.d.ts.map +1 -0
  124. package/dist/styles/registry.js +96 -0
  125. package/dist/styles/registry.js.map +1 -0
  126. package/dist/util/auth-store.d.ts +12 -0
  127. package/dist/util/auth-store.d.ts.map +1 -0
  128. package/dist/util/auth-store.js +46 -0
  129. package/dist/util/auth-store.js.map +1 -0
  130. package/dist/util/id.d.ts +2 -0
  131. package/dist/util/id.d.ts.map +1 -0
  132. package/dist/util/id.js +14 -0
  133. package/dist/util/id.js.map +1 -0
  134. package/dist/util/json.d.ts +3 -0
  135. package/dist/util/json.d.ts.map +1 -0
  136. package/dist/util/json.js +9 -0
  137. package/dist/util/json.js.map +1 -0
  138. package/dist/util/open.d.ts +2 -0
  139. package/dist/util/open.d.ts.map +1 -0
  140. package/dist/util/open.js +21 -0
  141. package/dist/util/open.js.map +1 -0
  142. package/dist/util/paths.d.ts +9 -0
  143. package/dist/util/paths.d.ts.map +1 -0
  144. package/dist/util/paths.js +21 -0
  145. package/dist/util/paths.js.map +1 -0
  146. package/package.json +37 -0
  147. package/studio/assets/index-BgiuT_Mv.css +1 -0
  148. package/studio/assets/index-DnN633_x.js +9 -0
  149. package/studio/index.html +13 -0
  150. package/styles/clean-premium/meta.json +7 -0
  151. package/styles/clean-premium/prompt.md +16 -0
@@ -0,0 +1,20 @@
1
+ import type { StyleMeta } from "../schema/style-meta.js";
2
+ export interface StyleInfo {
3
+ name: string;
4
+ meta: StyleMeta;
5
+ installed: boolean;
6
+ bundled: boolean;
7
+ }
8
+ export interface LoadedStyle {
9
+ meta: StyleMeta;
10
+ promptTemplate: string;
11
+ }
12
+ /** List all bundled styles */
13
+ export declare function listBundledStyles(): Promise<string[]>;
14
+ /** List installed styles in .shots/styles/ */
15
+ export declare function listInstalledStyles(): Promise<string[]>;
16
+ /** Get info about all styles (bundled + installed) */
17
+ export declare function listAllStyles(): Promise<StyleInfo[]>;
18
+ /** Load an installed style's meta + prompt template */
19
+ export declare function loadInstalledStyle(name: string): Promise<LoadedStyle | null>;
20
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/styles/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAIzD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB;AAWD,8BAA8B;AAC9B,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ3D;AAED,8CAA8C;AAC9C,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7D;AAED,sDAAsD;AACtD,wBAAsB,aAAa,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAyC1D;AAED,uDAAuD;AACvD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA2B7B"}
@@ -0,0 +1,96 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { readJson } from "../util/json.js";
4
+ import { shotsDir, bundledStylesPath } from "../util/paths.js";
5
+ async function dirExists(p) {
6
+ try {
7
+ const stat = await fs.stat(p);
8
+ return stat.isDirectory();
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /** List all bundled styles */
15
+ export async function listBundledStyles() {
16
+ const stylesPath = bundledStylesPath();
17
+ try {
18
+ const entries = await fs.readdir(stylesPath, { withFileTypes: true });
19
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
20
+ }
21
+ catch {
22
+ return [];
23
+ }
24
+ }
25
+ /** List installed styles in .shots/styles/ */
26
+ export async function listInstalledStyles() {
27
+ const stylesPath = path.join(shotsDir(), "styles");
28
+ try {
29
+ const entries = await fs.readdir(stylesPath, { withFileTypes: true });
30
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
31
+ }
32
+ catch {
33
+ return [];
34
+ }
35
+ }
36
+ /** Get info about all styles (bundled + installed) */
37
+ export async function listAllStyles() {
38
+ const bundled = await listBundledStyles();
39
+ const installed = await listInstalledStyles();
40
+ const allNames = [...new Set([...bundled, ...installed])];
41
+ const styles = [];
42
+ for (const name of allNames) {
43
+ const isBundled = bundled.includes(name);
44
+ const isInstalled = installed.includes(name);
45
+ // Read meta from installed version if available, else from bundled
46
+ const metaDir = isInstalled
47
+ ? path.join(shotsDir(), "styles", name)
48
+ : path.join(bundledStylesPath(), name);
49
+ try {
50
+ const meta = await readJson(path.join(metaDir, "meta.json"));
51
+ styles.push({
52
+ name,
53
+ meta,
54
+ installed: isInstalled,
55
+ bundled: isBundled,
56
+ });
57
+ }
58
+ catch {
59
+ styles.push({
60
+ name,
61
+ meta: {
62
+ name,
63
+ displayName: name,
64
+ description: "",
65
+ visualTone: "",
66
+ panelTypes: [],
67
+ },
68
+ installed: isInstalled,
69
+ bundled: isBundled,
70
+ });
71
+ }
72
+ }
73
+ return styles;
74
+ }
75
+ /** Load an installed style's meta + prompt template */
76
+ export async function loadInstalledStyle(name) {
77
+ const candidateDirs = [
78
+ path.join(shotsDir(), "styles", name),
79
+ path.join(bundledStylesPath(), name),
80
+ ];
81
+ const styleDir = (await Promise.all(candidateDirs.map(async (candidate) => ({
82
+ candidate,
83
+ exists: await dirExists(candidate),
84
+ })))).find((result) => result.exists)?.candidate;
85
+ if (!styleDir)
86
+ return null;
87
+ try {
88
+ const meta = await readJson(path.join(styleDir, "meta.json"));
89
+ const promptTemplate = await fs.readFile(path.join(styleDir, "prompt.md"), "utf-8");
90
+ return { meta, promptTemplate };
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/styles/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface ManagedAuth {
2
+ apiKey: string;
3
+ apiUrl: string;
4
+ createdAt: string;
5
+ }
6
+ export declare function authDir(): string;
7
+ export declare function authFile(): string;
8
+ export declare function defaultApiUrl(): string;
9
+ export declare function readManagedAuth(): Promise<ManagedAuth | null>;
10
+ export declare function writeManagedAuth(auth: ManagedAuth): Promise<void>;
11
+ export declare function clearManagedAuth(): Promise<void>;
12
+ //# sourceMappingURL=auth-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../../src/util/auth-store.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAanE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMtD"}
@@ -0,0 +1,46 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ const DEFAULT_API_URL = "https://shots.run";
5
+ export function authDir() {
6
+ return path.join(os.homedir(), ".shots");
7
+ }
8
+ export function authFile() {
9
+ return path.join(authDir(), "auth.json");
10
+ }
11
+ export function defaultApiUrl() {
12
+ return process.env.SHOTS_API_URL || DEFAULT_API_URL;
13
+ }
14
+ export async function readManagedAuth() {
15
+ try {
16
+ const raw = await fs.readFile(authFile(), "utf-8");
17
+ const parsed = JSON.parse(raw);
18
+ if (!parsed.apiKey)
19
+ return null;
20
+ return {
21
+ apiKey: parsed.apiKey,
22
+ apiUrl: parsed.apiUrl || defaultApiUrl(),
23
+ createdAt: parsed.createdAt || "",
24
+ };
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ export async function writeManagedAuth(auth) {
31
+ await fs.mkdir(authDir(), { recursive: true, mode: 0o700 });
32
+ await fs.writeFile(authFile(), JSON.stringify(auth, null, 2) + "\n", {
33
+ encoding: "utf-8",
34
+ mode: 0o600,
35
+ });
36
+ await fs.chmod(authFile(), 0o600);
37
+ }
38
+ export async function clearManagedAuth() {
39
+ try {
40
+ await fs.unlink(authFile());
41
+ }
42
+ catch {
43
+ // Already logged out.
44
+ }
45
+ }
46
+ //# sourceMappingURL=auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/util/auth-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAE5C,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,eAAe,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,aAAa,EAAE;YACxC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE;SAClC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAiB;IACtD,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QACnE,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IACH,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function generateId(existing: Set<string>): string;
2
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAUxD"}
@@ -0,0 +1,14 @@
1
+ const ID_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
2
+ export function generateId(existing) {
3
+ for (let attempt = 0; attempt < 100; attempt++) {
4
+ let suffix = "";
5
+ for (let i = 0; i < 6; i++) {
6
+ suffix += ID_CHARS[Math.floor(Math.random() * ID_CHARS.length)];
7
+ }
8
+ const id = `shot-${suffix}`;
9
+ if (!existing.has(id))
10
+ return id;
11
+ }
12
+ throw new Error("Failed to generate unique ID after 100 attempts");
13
+ }
14
+ //# sourceMappingURL=id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/util/id.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,sCAAsC,CAAC;AAExD,MAAM,UAAU,UAAU,CAAC,QAAqB;IAC9C,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;QAC/C,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,EAAE,GAAG,QAAQ,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,OAAO,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function readJson<T>(filePath: string): Promise<T>;
2
+ export declare function writeJson(filePath: string, data: unknown): Promise<void>;
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/util/json.ts"],"names":[],"mappings":"AAEA,wBAAsB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAG9D;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E"}
@@ -0,0 +1,9 @@
1
+ import fs from "node:fs/promises";
2
+ export async function readJson(filePath) {
3
+ const raw = await fs.readFile(filePath, "utf-8");
4
+ return JSON.parse(raw);
5
+ }
6
+ export async function writeJson(filePath, data) {
7
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
8
+ }
9
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/util/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,QAAgB;IAChD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,IAAa;IAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function openPath(targetPath: string): boolean;
2
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/util/open.ts"],"names":[],"mappings":"AAcA,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CASpD"}
@@ -0,0 +1,21 @@
1
+ import { execFileSync } from "node:child_process";
2
+ function openCommandForCurrentPlatform() {
3
+ if (process.platform === "darwin") {
4
+ return { command: "open", args: [] };
5
+ }
6
+ if (process.platform === "win32") {
7
+ return { command: "cmd", args: ["/c", "start", ""] };
8
+ }
9
+ return { command: "xdg-open", args: [] };
10
+ }
11
+ export function openPath(targetPath) {
12
+ const { command, args } = openCommandForCurrentPlatform();
13
+ try {
14
+ execFileSync(command, [...args, targetPath], { stdio: "ignore" });
15
+ return true;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ //# sourceMappingURL=open.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/util/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,SAAS,6BAA6B;IACpC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACvC,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IACvD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,UAAkB;IACzC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,6BAA6B,EAAE,CAAC;IAE1D,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** .shots/ workspace directory in the user's project */
2
+ export declare function shotsDir(cwd?: string): string;
3
+ /** Root of the Shots package (where package.json lives) */
4
+ export declare function packageRoot(): string;
5
+ /** Path to the bundled styles directory */
6
+ export declare function bundledStylesPath(): string;
7
+ /** Path to the bundled local studio app */
8
+ export declare function bundledStudioPath(): string;
9
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":"AAGA,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,GAAG,SAAgB,GAAG,MAAM,CAEpD;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,IAAI,MAAM,CAIpC;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ /** .shots/ workspace directory in the user's project */
4
+ export function shotsDir(cwd = process.cwd()) {
5
+ return path.resolve(cwd, ".shots");
6
+ }
7
+ /** Root of the Shots package (where package.json lives) */
8
+ export function packageRoot() {
9
+ const thisFile = fileURLToPath(import.meta.url);
10
+ // dist/util/paths.js -> package root (two levels up from dist/)
11
+ return path.resolve(path.dirname(thisFile), "..", "..");
12
+ }
13
+ /** Path to the bundled styles directory */
14
+ export function bundledStylesPath() {
15
+ return path.join(packageRoot(), "styles");
16
+ }
17
+ /** Path to the bundled local studio app */
18
+ export function bundledStudioPath() {
19
+ return path.join(packageRoot(), "studio");
20
+ }
21
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/util/paths.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,wDAAwD;AACxD,MAAM,UAAU,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW;IACzB,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,gEAAgE;IAChE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@hitslop/shots",
3
+ "version": "0.1.0",
4
+ "description": "AI-powered App Store screenshot generator",
5
+ "type": "module",
6
+ "bin": {
7
+ "shots": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "postbuild": "chmod +x dist/cli.js",
12
+ "dev": "tsc --watch",
13
+ "typecheck": "tsc --noEmit"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "studio",
18
+ "styles",
19
+ "SKILL.md"
20
+ ],
21
+ "dependencies": {
22
+ "@effect/cli": "^0.75.1",
23
+ "@effect/platform-node": "^0.106.0",
24
+ "@inquirer/select": "^5.1.5",
25
+ "chalk": "^5.6.2",
26
+ "effect": "^3.21.2",
27
+ "@fal-ai/client": "^1.10.1",
28
+ "openai": "^6.38.0",
29
+ "replicate": "^1.4.0",
30
+ "ora": "^9.4.0",
31
+ "sharp": "^0.34.5"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^25.8.0",
35
+ "typescript": "^6.0.3"
36
+ }
37
+ }
@@ -0,0 +1 @@
1
+ :root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;color:#202522;font-synthesis:none;text-rendering:optimizelegibility;background:#eef3f0;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}body{min-width:320px;min-height:100vh;margin:0}button,input{font:inherit}.shell{width:min(1480px,100vw - 32px);margin:0 auto;padding:28px 0 48px}.loading{place-items:center;min-height:100vh;display:grid}.topline{letter-spacing:0;text-transform:uppercase;background:#fbfcf8;border:1px solid #cfd8d3;padding:10px 14px;font-size:13px}.workspace-header{border-bottom:1px solid #cfd8d3;justify-content:space-between;align-items:end;gap:24px;padding-bottom:22px;display:flex}.eyebrow{letter-spacing:0;text-transform:uppercase;color:#0f6f63;margin:0 0 6px;font-size:12px;font-weight:700}h1,h2,h3,p{margin:0}h1{letter-spacing:0;max-width:900px;font-size:64px;line-height:.92}h2{letter-spacing:0;font-size:18px;line-height:1.1}h3{letter-spacing:0;font-size:20px;line-height:1.1}.pathline{overflow-wrap:anywhere;color:#67736d;max-width:900px;margin-top:12px;font-size:13px}.ghost-button,.upload-button{color:#fbfcf8;cursor:pointer;background:#202522;border:1px solid #202522;border-radius:4px;place-items:center;min-width:86px;height:38px;display:inline-grid}.ghost-button{color:#202522;background:0 0}.upload-button input{clip:rect(0 0 0 0);white-space:nowrap;block-size:1px;inline-size:1px;position:absolute;overflow:hidden}.metrics{background:#cfd8d3;border:1px solid #cfd8d3;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;margin:22px 0;display:grid}.metrics div{background:#fbfcf8;min-height:108px;padding:18px}.metrics span{text-overflow:ellipsis;white-space:nowrap;max-width:100%;font-size:28px;font-weight:760;line-height:1.1;display:block;overflow:hidden}.metrics p,.bucket-header p,.section-header p,.run-header p,.asset-tile small,.run-footer,.panel-preview span{color:#67736d;margin-top:8px;font-size:12px;line-height:1.4}.layout{grid-template-columns:minmax(360px,.75fr) minmax(0,1.25fr);align-items:start;gap:22px;display:grid}.sources,.runs{gap:18px;display:grid}.bucket,.runs,.run,.uninitialized{background:#fbfcf8;border:1px solid #d8d0c2}.bucket-header,.section-header,.run-header{border-bottom:1px solid #dce4df;justify-content:space-between;align-items:start;gap:16px;padding:16px;display:flex}.asset-grid{background:#dce4df;grid-template-columns:repeat(auto-fill,minmax(136px,1fr));gap:1px;display:grid}.asset-tile,.panel-preview{min-width:0;color:inherit;background:#fbfcf8;text-decoration:none}.asset-tile{grid-template-rows:128px auto auto;padding:10px;display:grid}.asset-tile img{object-fit:cover;background:#e5ece8;border:1px solid #dce4df;width:100%;height:128px}.asset-tile span{text-overflow:ellipsis;white-space:nowrap;margin-top:10px;font-size:13px;font-weight:700;overflow:hidden}.empty-strip,.error-strip{color:#67736d;background:#fbfcf8;padding:18px}.error-strip{color:#7b2440;border:1px solid #a34562;margin-top:16px}.runs{padding-bottom:18px}.run{margin:0 18px}.run-meta,.run-footer{flex-wrap:wrap;justify-content:flex-end;gap:8px;display:flex}.run-meta span,.run-footer span{color:#424c47;background:#eef3f0;border:1px solid #dce4df;align-items:center;min-height:28px;padding:0 9px;display:inline-flex}.run-images{background:#dce4df;grid-template-columns:repeat(auto-fit,minmax(128px,1fr));gap:1px;display:grid}.panel-preview{grid-template-rows:260px auto;padding:12px;display:grid}.panel-preview img{object-fit:contain;background:#e5ece8;border:1px solid #dce4df;width:100%;height:260px}.run-footer{border-top:1px solid #dce4df;justify-content:flex-start;padding:14px 16px 16px}.uninitialized{margin-top:22px;padding:22px}.uninitialized code{color:#fbfcf8;background:#202522;margin-top:14px;padding:8px 10px;display:inline-block}@media (width<=900px){h1{font-size:46px}.workspace-header{flex-direction:column;align-items:start}.metrics{grid-template-columns:repeat(2,minmax(0,1fr))}.layout{grid-template-columns:1fr}}@media (width<=560px){h1{font-size:36px}.shell{width:min(100vw - 20px,1480px);padding-top:16px}.metrics{grid-template-columns:1fr}.bucket-header,.section-header,.run-header{flex-direction:column}.run-meta{justify-content:flex-start}}