@claudein.org/cli 0.1.20 → 0.1.31

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/dist/index.js CHANGED
@@ -9886,7 +9886,10 @@ var links = {
9886
9886
  _: "/",
9887
9887
  auth: {
9888
9888
  google: `/auth/google`,
9889
- linkedin: `/auth/linkedin`
9889
+ linkedin: `/auth/linkedin`,
9890
+ facebook: `/auth/facebook`,
9891
+ instagram: `/auth/instagram`,
9892
+ youtube: `/auth/youtube`
9890
9893
  },
9891
9894
  close: `/close`,
9892
9895
  guide: `/guide`,
@@ -24174,22 +24177,31 @@ config(en_default());
24174
24177
  var zod_default = exports_external;
24175
24178
 
24176
24179
  // ../common/index.ts
24180
+ var Platform = zod_default.enum(["LinkedIn", "Facebook", "Instagram", "YouTube"]);
24177
24181
  var yml;
24178
24182
  ((yml) => {
24179
- yml.Media = zod_default.object({
24180
- type: zod_default.union([zod_default.literal("image"), zod_default.literal("video")]),
24181
- src: zod_default.string(),
24183
+ const BasicMedia = zod_default.object({
24182
24184
  title: zod_default.string().optional(),
24183
24185
  description: zod_default.string().optional()
24184
24186
  });
24185
- const Base = zod_default.object({
24186
- created: zod_default.iso.date()
24187
+ yml.Image = BasicMedia.extend({
24188
+ type: zod_default.literal("image"),
24189
+ src: zod_default.string().regex(/.*\.(jpg|jpeg|png)$/)
24187
24190
  });
24188
- yml.PostText = Base.extend({
24191
+ yml.Video = BasicMedia.extend({
24192
+ type: zod_default.literal("video"),
24193
+ src: zod_default.string().regex(/.*\.(mp4|mkv|avi)$/)
24194
+ });
24195
+ yml.Media = zod_default.discriminatedUnion("type", [yml.Image, yml.Video]);
24196
+ const BasePost = zod_default.object({
24197
+ created: zod_default.iso.date(),
24198
+ platforms: zod_default.array(Platform)
24199
+ });
24200
+ yml.PostText = BasePost.extend({
24189
24201
  type: zod_default.literal("text"),
24190
24202
  text: zod_default.string()
24191
24203
  });
24192
- yml.PostMedia = Base.extend({
24204
+ yml.PostMedia = BasePost.extend({
24193
24205
  type: zod_default.literal("media"),
24194
24206
  text: zod_default.string().optional(),
24195
24207
  media: yml.Media
@@ -24199,12 +24211,10 @@ var yml;
24199
24211
  })(yml ||= {});
24200
24212
  var proto;
24201
24213
  ((proto) => {
24202
- const Media = yml.Media.extend({
24203
- base64: zod_default.string()
24204
- });
24205
- const PostMedia = yml.PostMedia.extend({
24206
- media: Media
24207
- });
24214
+ const Image = yml.Image.extend({ base64: zod_default.string() });
24215
+ const Video = yml.Video.extend({ base64: zod_default.string() });
24216
+ const Media = zod_default.discriminatedUnion("type", [Image, Video]);
24217
+ const PostMedia = yml.PostMedia.extend({ media: Media });
24208
24218
  proto.Post = zod_default.discriminatedUnion("type", [yml.PostText, PostMedia]);
24209
24219
  proto.Payload = zod_default.object({
24210
24220
  hash: zod_default.string(),
@@ -25621,8 +25631,6 @@ import crypto from "crypto";
25621
25631
  import { watch } from "fs";
25622
25632
  import { cp, mkdir, readdir as readdir2, readFile, writeFile } from "fs/promises";
25623
25633
  import { createRequire as createRequire2 } from "module";
25624
- import { homedir } from "os";
25625
- import { dirname as dirname2, join as join2 } from "path";
25626
25634
 
25627
25635
  // ../node_modules/.bun/nanostores@1.3.0/node_modules/nanostores/clean-stores/index.js
25628
25636
  var clean = Symbol("clean");
@@ -26199,6 +26207,10 @@ defineLazyProperty(apps, "browser", () => "browser");
26199
26207
  defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
26200
26208
  var open_default = open;
26201
26209
 
26210
+ // src/index.ts
26211
+ import { homedir } from "os";
26212
+ import { dirname as dirname2, join as join2 } from "path";
26213
+
26202
26214
  // ../node_modules/.bun/stable-hash@0.0.6/node_modules/stable-hash/dist/index.mjs
26203
26215
  var o = new WeakMap;
26204
26216
  var u = 0;
@@ -26226,6 +26238,9 @@ function stableHash(t) {
26226
26238
  return c ? t.toJSON() : i === "symbol" ? t.toString() : i === "string" ? JSON.stringify(t) : "" + t;
26227
26239
  }
26228
26240
 
26241
+ // src/index.ts
26242
+ import { fileURLToPath as fileURLToPath2 } from "url";
26243
+
26229
26244
  // ../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
26230
26245
  var composer = require_composer();
26231
26246
  var Document = require_Document();
@@ -26273,7 +26288,6 @@ var $visit = visit.visit;
26273
26288
  var $visitAsync = visit.visitAsync;
26274
26289
 
26275
26290
  // src/index.ts
26276
- import { fileURLToPath as fileURLToPath2 } from "url";
26277
26291
  var { version: version2 } = createRequire2(import.meta.url)("../package.json");
26278
26292
  var DOMAIN = process.env.CIN_ENV === "dev" ? "localhost:3000" : "claudein.org";
26279
26293
  function hash2(post) {
@@ -26309,6 +26323,7 @@ var posts = {
26309
26323
  posts: [{
26310
26324
  type: "text",
26311
26325
  created: formatter.format(new Date),
26326
+ platforms: ["LinkedIn"],
26312
26327
  text: "I'm using ClaudeIn to share my thoughts and ideas!"
26313
26328
  }]
26314
26329
  };
@@ -26346,7 +26361,7 @@ var start = command("start").meta({
26346
26361
  }
26347
26362
  });
26348
26363
  const protoPosts = await ps2ps(posts2);
26349
- const payloads = protoPosts.map((post) => ({ hash: hash2(post), post })).sort((a, b) => a.post.created.localeCompare(b.post.created));
26364
+ const payloads = protoPosts.map((post) => ({ hash: hash2(post), post })).sort((a, b) => b.post.created.localeCompare(a.post.created));
26350
26365
  $payloads.set(payloads);
26351
26366
  } catch (err) {
26352
26367
  console.error("Failed to load posts:", err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claudein.org/cli",
3
- "version": "0.1.20",
3
+ "version": "0.1.31",
4
4
  "description": "Post to LinkedIn from the command line",
5
5
  "type": "module",
6
6
  "repository": {
@@ -26,6 +26,7 @@
26
26
  "dependencies": {
27
27
  "@types/ws": "^8.18.1",
28
28
  "@versecafe/zcli": "^0.1.2",
29
+ "image-size": "^2.0.2",
29
30
  "nanostores": "^1.3.0",
30
31
  "open": "^10.1.0",
31
32
  "stable-hash": "^0.0.6",
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: claudein
3
- description: Create LinkedIn posts using the claudein CLI. Use when the user wants to write, draft, or schedule LinkedIn posts, or when working with any .yml posts file.
3
+ description: Create social media posts (LinkedIn, Facebook, Instagram, YouTube) using the claudein CLI. Use when the user wants to write, draft, or schedule posts, or when working with any .yml posts file.
4
4
  allowed-tools: Edit, Write, Bash(cin *), Bash(pgrep *), Bash(curl *)
5
5
  ---
6
6
 
7
- # claudein — LinkedIn posts from the CLI
7
+ # claudein — social media posts from the CLI
8
8
 
9
9
  ## Live schema
10
10
 
@@ -18,24 +18,49 @@ The default file is `posts.yml` but users can use any `.yml` file (pass it to `c
18
18
 
19
19
  `cin start` watches the file for changes and updates the browser preview live — always edit the file in place, never delete and recreate it.
20
20
 
21
+ ## Platforms
22
+
23
+ Each post must include a `platforms` field listing the target platforms. The client decides which platforms a post is for — the web app uses this list to show the correct publish buttons.
24
+
25
+ Available platforms: `LinkedIn`, `Facebook`, `Instagram`, `YouTube`
26
+
27
+ ```yaml
28
+ posts:
29
+ - type: text
30
+ created: 2026-01-01
31
+ platforms: [LinkedIn]
32
+ text: "Hello LinkedIn!"
33
+
34
+ - type: media
35
+ created: 2026-01-02
36
+ platforms: [Instagram, Facebook]
37
+ media:
38
+ type: image
39
+ src: photo.jpg
40
+ ```
41
+
21
42
  ## Workflow
22
43
 
23
44
  1. Write or edit the `.yml` posts file
24
45
  2. Check if `cin start` is already running: `pgrep -fa "cin start"` — if it is, skip step 3
25
46
  3. If not running: `cin start [file]` — opens the live browser preview
26
- 4. Click "Post" in the browser to publish to LinkedIn
47
+ 4. Click the platform button in the browser to publish
48
+
49
+ ## Media guidelines
27
50
 
28
- ## Media guidelines (LinkedIn)
51
+ ### LinkedIn
29
52
 
30
- When generating or sourcing images and videos (e.g. with Remotion), target LinkedIn's specs:
53
+ **Images:** PNG or JPG, max 20 MB, aspect ratio 1:2.4 to 2.4:1
54
+ **Videos:** MP4 H.264, max 5 GB, 3–600 seconds, aspect ratio 1:1 to 4:5 recommended
31
55
 
32
- **Both images and videos:** 1:1 to 4:5 aspect ratio, 1080×1080 px up to 1080×1350 px
56
+ ### Instagram
33
57
 
34
- **Images:** PNG or JPG
58
+ **Images:** PNG or JPG, max 8 MB, aspect ratio 4:5 to 1.91:1
59
+ **Videos:** MP4, max 650 MB, 3–60 seconds
35
60
 
36
- **Videos:** MP4, H.264
61
+ ### YouTube
37
62
 
38
- Content outside the 1:1–4:5 range may be cropped or rejected by LinkedIn.
63
+ **Videos:** MP4, any duration
39
64
 
40
65
  ### Remotion
41
66