chirpie 1.0.43 → 1.0.45
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 +25 -3
- package/dist/index.js +190 -38
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -30,9 +30,9 @@ export CHIRPIE_API_KEY=chirpie_sk_...
|
|
|
30
30
|
| Command | What it does |
|
|
31
31
|
|---------|--------------|
|
|
32
32
|
| `chirpie login` / `logout` / `auth` / `whoami` | Manage credentials |
|
|
33
|
-
| `chirpie post <text>` | Create a post. `-a` account, `-m` media files or URLs, `--alt` descriptions, `-s` schedule |
|
|
34
|
-
| `chirpie thread <post> <post> ...` | Create a 2 to 25 post thread. `-f` takes a JSON payload file |
|
|
35
|
-
| `chirpie posts` | List posts. `--status`, `--account`, `--limit` |
|
|
33
|
+
| `chirpie post <text>` | Create a post. `-a` account (repeat it for several accounts), `-m` media files or URLs, `--alt` descriptions, `--config` per-account overrides, `-s` schedule |
|
|
34
|
+
| `chirpie thread <post> <post> ...` | Create a 2 to 25 post thread. `-a` is repeatable, `--config` takes per-account posts, `-f` takes a JSON payload file |
|
|
35
|
+
| `chirpie posts` | List posts. `--status`, `--account`, `--group`, `--limit` |
|
|
36
36
|
| `chirpie posts get <id>` | Fetch one post |
|
|
37
37
|
| `chirpie posts update <id>` | Edit a post that has not published yet. `--text`, `--media`, `--alt`, `--clear-media`, `--schedule-at`. Leaving `--schedule-at` out keeps the time it already has |
|
|
38
38
|
| `chirpie posts delete <id>` | Delete a post. Deleting any post of a scheduled thread cancels the thread |
|
|
@@ -70,6 +70,28 @@ chirpie thread "One" "Two" "Three" -a 550e8400-e29b-41d4-a716-446655440000
|
|
|
70
70
|
chirpie posts --status scheduled
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
+
## Several accounts at once
|
|
74
|
+
|
|
75
|
+
Repeat `-a` to publish the same post to up to 25 accounts in one call.
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
chirpie post "Shipped a new release." -a "$X_ACCOUNT" -a "$BSKY_ACCOUNT"
|
|
79
|
+
|
|
80
|
+
# Give one account its own text, inline or from a file
|
|
81
|
+
chirpie post "Shipped a new release." -a "$X_ACCOUNT" -a "$BSKY_ACCOUNT" \
|
|
82
|
+
--config "{\"$BSKY_ACCOUNT\":{\"text\":\"Shorter, for Bluesky\"}}"
|
|
83
|
+
chirpie post "Shipped a new release." -a "$X_ACCOUNT" -a "$BSKY_ACCOUNT" --config ./overrides.json
|
|
84
|
+
|
|
85
|
+
# A thread, with a thread of its own for one account
|
|
86
|
+
chirpie thread "One" "Two" -a "$X_ACCOUNT" -a "$BSKY_ACCOUNT" \
|
|
87
|
+
--config "{\"$BSKY_ACCOUNT\":{\"posts\":[{\"text\":\"A\"},{\"text\":\"B\"}]}}"
|
|
88
|
+
|
|
89
|
+
# Read the whole group back
|
|
90
|
+
chirpie posts --group 550e8400-e29b-41d4-a716-446655440000
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
One line is printed per account, with a group ID above them. An account the platform refused is shown with its error while the others stay published, and the command leaves with a non-zero status when any account failed. An override says only what differs, and naming media replaces the shared media for that account.
|
|
94
|
+
|
|
73
95
|
## JSON output
|
|
74
96
|
|
|
75
97
|
Every command accepts `--json` and prints the raw API response, which is what you want in a script:
|
package/dist/index.js
CHANGED
|
@@ -181,28 +181,127 @@ async function resolveMediaArgs(client, media, alt) {
|
|
|
181
181
|
var MEDIA_OPTION_HELP = "Image or video files on this machine, or public URLs. Files are uploaded first. Image caps: X, Bluesky, LinkedIn and Mastodon 4, Threads 1, Instagram, Facebook and Telegram 10. Video: X, Mastodon and Telegram only, one per post, never with images. Anything a platform cannot take is refused rather than dropped.";
|
|
182
182
|
var ALT_OPTION_HELP = "Describe each item for people using a screen reader, in the same order as --media. Carried to X, Bluesky, LinkedIn, Mastodon, Instagram and Facebook.";
|
|
183
183
|
|
|
184
|
-
// src/
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
// src/lib/accounts.ts
|
|
185
|
+
import { readFileSync } from "fs";
|
|
186
|
+
function collect(value, previous = []) {
|
|
187
|
+
return [...previous, value];
|
|
188
|
+
}
|
|
189
|
+
async function resolveSingleAccountId(client) {
|
|
190
|
+
const accounts = await client.listAccounts();
|
|
191
|
+
const active = accounts.filter((a) => a.is_active);
|
|
192
|
+
if (active.length === 0) {
|
|
193
|
+
error("No connected accounts. Run: chirpie accounts connect");
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
if (active.length > 1) {
|
|
197
|
+
error("Multiple accounts found. Use --account <id> to specify:");
|
|
198
|
+
active.forEach((a) => console.log(` ${a.id} @${a.username}`));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
return active[0].id;
|
|
202
|
+
}
|
|
203
|
+
function parseAccountConfigurations(value) {
|
|
204
|
+
if (!value) return void 0;
|
|
205
|
+
const trimmed = value.trim();
|
|
206
|
+
let raw;
|
|
207
|
+
if (trimmed.startsWith("{")) {
|
|
208
|
+
raw = trimmed;
|
|
209
|
+
} else {
|
|
210
|
+
try {
|
|
211
|
+
raw = readFileSync(trimmed, "utf8");
|
|
212
|
+
} catch {
|
|
213
|
+
error(`Could not read --config file: ${trimmed}`);
|
|
193
214
|
process.exit(1);
|
|
194
215
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
216
|
+
}
|
|
217
|
+
let parsed;
|
|
218
|
+
try {
|
|
219
|
+
parsed = JSON.parse(raw);
|
|
220
|
+
} catch {
|
|
221
|
+
error("--config must be a JSON object, or a path to a file holding one");
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
225
|
+
error("--config must be a JSON object keyed by account ID");
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
return parsed;
|
|
229
|
+
}
|
|
230
|
+
function printFanOut(groupId, lines) {
|
|
231
|
+
const failed = lines.filter((line) => !line.success);
|
|
232
|
+
console.log(`Group ${groupId}`);
|
|
233
|
+
for (const line of lines) {
|
|
234
|
+
if (line.success) {
|
|
235
|
+
const where = line.platform_post_url ? ` ${line.platform_post_url}` : "";
|
|
236
|
+
console.log(
|
|
237
|
+
`\x1B[32m\u2713\x1B[0m ${line.platform} ${line.account_id} ${line.status ?? ""} ${line.id ?? ""}${where}`.trimEnd()
|
|
238
|
+
);
|
|
239
|
+
} else {
|
|
240
|
+
const reason = line.error ? `${line.error.code}: ${line.error.message}` : "Failed";
|
|
241
|
+
console.log(
|
|
242
|
+
`\x1B[31m\u2717\x1B[0m ${line.platform} ${line.account_id} ${reason}`
|
|
243
|
+
);
|
|
199
244
|
}
|
|
200
|
-
accountId = active[0].id;
|
|
201
245
|
}
|
|
246
|
+
console.log(
|
|
247
|
+
`${lines.length - failed.length} of ${lines.length} accounts succeeded`
|
|
248
|
+
);
|
|
249
|
+
return failed.length;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/commands/post.ts
|
|
253
|
+
var postCommand = new Command3("post").description("Create a post").argument("<text>", "Post text").option(
|
|
254
|
+
"-a, --account <id>",
|
|
255
|
+
"Account ID. Repeat it to publish the same post to several accounts at once (up to 25)",
|
|
256
|
+
collect
|
|
257
|
+
).option("-m, --media <files...>", MEDIA_OPTION_HELP).option("--alt <text...>", ALT_OPTION_HELP).option(
|
|
258
|
+
"--config <json-or-file>",
|
|
259
|
+
'Per-account overrides as JSON, or a path to a JSON file holding them: { "<account id>": { "text": "...", "media_urls": ["..."] } }. Every key must be an account named with --account'
|
|
260
|
+
).option("-s, --schedule <datetime>", "Schedule for later. Any ISO 8601 timestamp with a timezone (2026-04-01T14:00:00Z or 2026-04-01T16:00:00+02:00). Posts publish within ~5 minutes of the scheduled time.").option("--json", "Output raw JSON").action(async (text, opts) => {
|
|
261
|
+
const client = getClient();
|
|
262
|
+
const named = opts.account ?? [];
|
|
263
|
+
if (opts.config && named.length === 0) {
|
|
264
|
+
error("--config names accounts, so pass --account <id> for each of them");
|
|
265
|
+
process.exit(1);
|
|
266
|
+
}
|
|
267
|
+
const accountIds = named.length > 0 ? named : [await resolveSingleAccountId(client)];
|
|
268
|
+
const fanOut = named.length > 1 || Boolean(opts.config);
|
|
202
269
|
try {
|
|
203
270
|
const media = await resolveMediaArgs(client, opts.media, opts.alt);
|
|
271
|
+
if (fanOut) {
|
|
272
|
+
const result = await client.createPost({
|
|
273
|
+
account_ids: accountIds,
|
|
274
|
+
text,
|
|
275
|
+
...media ? { media } : {},
|
|
276
|
+
...opts.config ? {
|
|
277
|
+
account_configurations: parseAccountConfigurations(
|
|
278
|
+
opts.config
|
|
279
|
+
)
|
|
280
|
+
} : {},
|
|
281
|
+
schedule_at: opts.schedule
|
|
282
|
+
});
|
|
283
|
+
if (opts.json) {
|
|
284
|
+
json(result);
|
|
285
|
+
if (result.results.some((r) => !r.success)) process.exit(1);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const failed = printFanOut(
|
|
289
|
+
result.group_id,
|
|
290
|
+
result.results.map((r) => ({
|
|
291
|
+
account_id: r.account_id,
|
|
292
|
+
platform: r.platform,
|
|
293
|
+
success: r.success,
|
|
294
|
+
id: r.post_id,
|
|
295
|
+
status: r.status,
|
|
296
|
+
platform_post_url: r.platform_post_url,
|
|
297
|
+
error: r.error
|
|
298
|
+
}))
|
|
299
|
+
);
|
|
300
|
+
if (failed > 0) process.exit(1);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
204
303
|
const post = await client.createPost({
|
|
205
|
-
account_id:
|
|
304
|
+
account_id: accountIds[0],
|
|
206
305
|
text,
|
|
207
306
|
...media ? { media } : {},
|
|
208
307
|
schedule_at: opts.schedule
|
|
@@ -222,7 +321,7 @@ var postCommand = new Command3("post").description("Create a post").argument("<t
|
|
|
222
321
|
|
|
223
322
|
// src/commands/thread.ts
|
|
224
323
|
import { Command as Command4 } from "commander";
|
|
225
|
-
import { readFileSync } from "fs";
|
|
324
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
226
325
|
function parseMediaSpec(spec) {
|
|
227
326
|
const m = spec.match(/^(\d+):(.+)$/);
|
|
228
327
|
if (!m) return null;
|
|
@@ -238,7 +337,11 @@ function parseAltSpec(spec) {
|
|
|
238
337
|
alts: m[2].split(",").map((a) => a.trim())
|
|
239
338
|
};
|
|
240
339
|
}
|
|
241
|
-
var threadCommand = new Command4("thread").description("Create a thread").argument("[posts...]", "Thread posts (each argument is one post). Omit when using --file.").option(
|
|
340
|
+
var threadCommand = new Command4("thread").description("Create a thread").argument("[posts...]", "Thread posts (each argument is one post). Omit when using --file.").option(
|
|
341
|
+
"-a, --account <id>",
|
|
342
|
+
"Account ID. Repeat it to publish the same thread to several accounts at once (up to 25)",
|
|
343
|
+
collect
|
|
344
|
+
).option(
|
|
242
345
|
"-m, --media <specs...>",
|
|
243
346
|
'Per-post media as "INDEX:file1,file2" (repeatable). Files on this machine are uploaded first; public URLs are used as they are. Example: -m 0:./shot.png 2:https://b.png,https://c.png'
|
|
244
347
|
).option(
|
|
@@ -246,32 +349,27 @@ var threadCommand = new Command4("thread").description("Create a thread").argume
|
|
|
246
349
|
'Per-post alt text as "INDEX:first,second", lining up with --media. Carried to X, Bluesky, LinkedIn, Mastodon, Instagram and Facebook.'
|
|
247
350
|
).option(
|
|
248
351
|
"-f, --file <path>",
|
|
249
|
-
"JSON file with a full thread payload: { posts: [{ text, media_urls? }, ...], schedule_at?: string }"
|
|
352
|
+
"JSON file with a full thread payload: { posts: [{ text, media_urls? }, ...], schedule_at?: string }. It may also carry account_ids and account_configurations."
|
|
353
|
+
).option(
|
|
354
|
+
"--config <json-or-file>",
|
|
355
|
+
`Per-account overrides as JSON, or a path to a JSON file holding them: { "<account id>": { "posts": [{ "text": "one" }, { "text": "two" }] } }. An account's posts replace the whole thread for that account`
|
|
250
356
|
).option("-s, --schedule <datetime>", "Schedule for later. Any ISO 8601 timestamp with a timezone (2026-04-01T14:00:00Z or 2026-04-01T16:00:00+02:00). Threads publish within ~5 minutes of the scheduled time.").option("--json", "Output raw JSON").action(async (posts, opts) => {
|
|
251
357
|
const client = getClient();
|
|
252
|
-
let accountId = opts.account;
|
|
253
|
-
if (!accountId) {
|
|
254
|
-
const accounts = await client.listAccounts();
|
|
255
|
-
const active = accounts.filter((a) => a.is_active);
|
|
256
|
-
if (active.length === 0) {
|
|
257
|
-
error("No connected accounts. Run: chirpie accounts connect");
|
|
258
|
-
process.exit(1);
|
|
259
|
-
}
|
|
260
|
-
if (active.length > 1) {
|
|
261
|
-
error("Multiple accounts found. Use --account <id> to specify:");
|
|
262
|
-
active.forEach((a) => console.log(` ${a.id} @${a.username}`));
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
265
|
-
accountId = active[0].id;
|
|
266
|
-
}
|
|
267
358
|
let postPayload;
|
|
268
359
|
let scheduleAt = opts.schedule;
|
|
360
|
+
let fileAccountIds;
|
|
361
|
+
let fileConfigurations;
|
|
269
362
|
if (opts.file) {
|
|
270
363
|
try {
|
|
271
|
-
const raw = JSON.parse(
|
|
364
|
+
const raw = JSON.parse(readFileSync2(opts.file, "utf8"));
|
|
272
365
|
if (!Array.isArray(raw.posts)) throw new Error("File must contain { posts: [...] }");
|
|
273
366
|
postPayload = raw.posts;
|
|
274
367
|
scheduleAt = scheduleAt ?? raw.schedule_at;
|
|
368
|
+
if (raw.account_ids !== void 0 && (!Array.isArray(raw.account_ids) || raw.account_ids.some((id) => typeof id !== "string"))) {
|
|
369
|
+
throw new Error("account_ids in the file must be an array of account IDs");
|
|
370
|
+
}
|
|
371
|
+
fileAccountIds = raw.account_ids;
|
|
372
|
+
fileConfigurations = raw.account_configurations;
|
|
275
373
|
} catch (err) {
|
|
276
374
|
error(err instanceof Error ? err.message : "Failed to read thread file");
|
|
277
375
|
process.exit(1);
|
|
@@ -314,9 +412,44 @@ var threadCommand = new Command4("thread").description("Create a thread").argume
|
|
|
314
412
|
}
|
|
315
413
|
}
|
|
316
414
|
}
|
|
415
|
+
const configurations = parseAccountConfigurations(opts.config) ?? fileConfigurations;
|
|
416
|
+
const named = opts.account ?? fileAccountIds ?? [];
|
|
417
|
+
if (configurations && named.length === 0) {
|
|
418
|
+
error("Per-account posts name accounts, so pass --account <id> for each of them");
|
|
419
|
+
process.exit(1);
|
|
420
|
+
}
|
|
421
|
+
const accountIds = named.length > 0 ? named : [await resolveSingleAccountId(client)];
|
|
422
|
+
const fanOut = named.length > 1 || Boolean(configurations);
|
|
317
423
|
try {
|
|
424
|
+
if (fanOut) {
|
|
425
|
+
const result = await client.createThread({
|
|
426
|
+
account_ids: accountIds,
|
|
427
|
+
posts: postPayload,
|
|
428
|
+
...configurations ? { account_configurations: configurations } : {},
|
|
429
|
+
schedule_at: scheduleAt
|
|
430
|
+
});
|
|
431
|
+
if (opts.json) {
|
|
432
|
+
json(result);
|
|
433
|
+
if (result.results.some((r) => !r.success)) process.exit(1);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const failed = printFanOut(
|
|
437
|
+
result.group_id,
|
|
438
|
+
result.results.map((r) => ({
|
|
439
|
+
account_id: r.account_id,
|
|
440
|
+
platform: r.platform,
|
|
441
|
+
success: r.success,
|
|
442
|
+
id: r.thread_id,
|
|
443
|
+
status: r.status,
|
|
444
|
+
platform_post_url: r.platform_post_url,
|
|
445
|
+
error: r.error
|
|
446
|
+
}))
|
|
447
|
+
);
|
|
448
|
+
if (failed > 0) process.exit(1);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
318
451
|
const thread = await client.createThread({
|
|
319
|
-
account_id:
|
|
452
|
+
account_id: accountIds[0],
|
|
320
453
|
posts: postPayload,
|
|
321
454
|
schedule_at: scheduleAt
|
|
322
455
|
});
|
|
@@ -333,6 +466,7 @@ var threadCommand = new Command4("thread").description("Create a thread").argume
|
|
|
333
466
|
|
|
334
467
|
// src/commands/posts.ts
|
|
335
468
|
import { Command as Command5 } from "commander";
|
|
469
|
+
import { postFailureReason } from "@chirpie/sdk";
|
|
336
470
|
|
|
337
471
|
// src/lib/flags.ts
|
|
338
472
|
function wantsJson(opts, cmd) {
|
|
@@ -341,12 +475,16 @@ function wantsJson(opts, cmd) {
|
|
|
341
475
|
}
|
|
342
476
|
|
|
343
477
|
// src/commands/posts.ts
|
|
344
|
-
var postsCommand = new Command5("posts").description("List, get, update, or delete posts").option("--status <status>", "Filter by status").option("--account <id>", "Filter by account").option(
|
|
478
|
+
var postsCommand = new Command5("posts").description("List, get, update, or delete posts").option("--status <status>", "Filter by status").option("--account <id>", "Filter by account").option(
|
|
479
|
+
"--group <id>",
|
|
480
|
+
"Only the posts of one fan-out, from the group ID a multi-account post returned"
|
|
481
|
+
).option("--limit <n>", "Limit results", "20").option("--json", "Output raw JSON").action(async (opts, cmd) => {
|
|
345
482
|
const client = getClient();
|
|
346
483
|
try {
|
|
347
484
|
const posts = await client.listPosts({
|
|
348
485
|
status: opts.status,
|
|
349
486
|
account_id: opts.account,
|
|
487
|
+
group_id: opts.group,
|
|
350
488
|
limit: parseInt(opts.limit)
|
|
351
489
|
});
|
|
352
490
|
if (wantsJson(opts, cmd)) {
|
|
@@ -357,7 +495,10 @@ var postsCommand = new Command5("posts").description("List, get, update, or dele
|
|
|
357
495
|
id: p.id.slice(0, 8),
|
|
358
496
|
status: p.status,
|
|
359
497
|
text: p.text.length > 50 ? p.text.slice(0, 50) + "..." : p.text,
|
|
360
|
-
created: p.created_at.slice(0, 10)
|
|
498
|
+
created: p.created_at.slice(0, 10),
|
|
499
|
+
// Why a post is not where you expected it. Empty for the ones
|
|
500
|
+
// that are exactly where you left them.
|
|
501
|
+
issue: postFailureReason(p) ?? ""
|
|
361
502
|
}))
|
|
362
503
|
);
|
|
363
504
|
}
|
|
@@ -380,6 +521,10 @@ postsCommand.command("get <id>").description("Get a post by ID").option("--json"
|
|
|
380
521
|
if (post.scheduled_at) console.log(`Scheduled: ${post.scheduled_at}`);
|
|
381
522
|
if (post.published_at) console.log(`Published: ${post.published_at}`);
|
|
382
523
|
if (post.platform_post_id) console.log(`Platform Post ID: ${post.platform_post_id}`);
|
|
524
|
+
if (post.platform_post_url) console.log(`URL: ${post.platform_post_url}`);
|
|
525
|
+
if (post.retry_count > 0) console.log(`Attempts: ${post.retry_count}`);
|
|
526
|
+
const issue = postFailureReason(post);
|
|
527
|
+
if (issue) console.log(`Issue: ${issue}`);
|
|
383
528
|
}
|
|
384
529
|
} catch (err) {
|
|
385
530
|
error(err instanceof Error ? err.message : "Failed to get post");
|
|
@@ -525,7 +670,7 @@ var accountsCommand = new Command6("accounts").description("List connected socia
|
|
|
525
670
|
// Inactive accounts are listed too, so a Facebook Page that was
|
|
526
671
|
// connected past the plan's account limit is visible and can be
|
|
527
672
|
// switched on with `chirpie accounts activate <id>`.
|
|
528
|
-
note: a.is_active ? "" : a.inactive_reason
|
|
673
|
+
note: a.is_active ? "" : inactiveNote(a.inactive_reason)
|
|
529
674
|
}))
|
|
530
675
|
);
|
|
531
676
|
}
|
|
@@ -534,6 +679,13 @@ var accountsCommand = new Command6("accounts").description("List connected socia
|
|
|
534
679
|
process.exit(1);
|
|
535
680
|
}
|
|
536
681
|
});
|
|
682
|
+
function inactiveNote(reason) {
|
|
683
|
+
if (reason === "plan_limit") return "over plan limit";
|
|
684
|
+
if (reason === "token_revoked" || reason === "token_expired" || reason === "reauth_required") {
|
|
685
|
+
return "needs reconnecting";
|
|
686
|
+
}
|
|
687
|
+
return "";
|
|
688
|
+
}
|
|
537
689
|
accountsCommand.command("activate").argument("<id>", "Account ID (from `chirpie accounts`)").description("Activate a connected account so it can publish").option("--json", "Output raw JSON").action(async (id, opts, cmd) => {
|
|
538
690
|
const client = getClient();
|
|
539
691
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chirpie",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.45",
|
|
4
4
|
"description": "Chirpie CLI: post to social media from the command line",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
],
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@chirpie/sdk": "^1.0.
|
|
47
|
+
"@chirpie/sdk": "^1.0.42",
|
|
48
48
|
"commander": "^13"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|