chirpie 1.0.14 → 1.0.16

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 (2) hide show
  1. package/dist/index.js +69 -3
  2. package/package.json +4 -3
package/dist/index.js CHANGED
@@ -157,7 +157,7 @@ function getClient() {
157
157
  }
158
158
 
159
159
  // src/commands/post.ts
160
- var postCommand = new Command3("post").description("Create a post").argument("<text>", "Post text").option("-a, --account <id>", "Account ID").option("-m, --media <urls...>", "Media URLs. Per-platform caps: X/Bluesky/Mastodon 4, LinkedIn 9, Threads/Pinterest/YouTube/GBP/Snapchat/Reddit 1, Instagram/Facebook/Telegram 10, TikTok up to 35 photos.").option("-s, --schedule <datetime>", "Schedule for later (ISO 8601, UTC). Posts publish within ~5 minutes of the scheduled time.").option("--json", "Output raw JSON").action(async (text, opts) => {
160
+ var postCommand = new Command3("post").description("Create a post").argument("<text>", "Post text").option("-a, --account <id>", "Account ID").option("-m, --media <urls...>", "Media URLs. Per-platform caps: X/Bluesky/Mastodon 4, LinkedIn 4, Threads/Pinterest/YouTube/GBP/Snapchat/Reddit 1, Instagram/Facebook/Telegram 10, TikTok up to 35 photos.").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) => {
161
161
  const client = getClient();
162
162
  let accountId = opts.account;
163
163
  if (!accountId) {
@@ -210,7 +210,7 @@ var threadCommand = new Command4("thread").description("Create a thread").argume
210
210
  ).option(
211
211
  "-f, --file <path>",
212
212
  "JSON file with a full thread payload: { posts: [{ text, media_urls? }, ...], schedule_at?: string }"
213
- ).option("-s, --schedule <datetime>", "Schedule for later (ISO 8601, UTC). Threads publish within ~5 minutes of the scheduled time.").option("--json", "Output raw JSON").action(async (posts, opts) => {
213
+ ).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) => {
214
214
  const client = getClient();
215
215
  let accountId = opts.account;
216
216
  if (!accountId) {
@@ -548,6 +548,70 @@ accountsCommand.command("connect-telegram").description("Connect a Telegram bot
548
548
  process.exit(1);
549
549
  }
550
550
  });
551
+ var xKeysCommand = accountsCommand.command("x-keys").description("Manage your own X developer app used to connect X accounts");
552
+ xKeysCommand.command("set").description("Set or replace your own X developer app credentials").requiredOption("--client-id <id>", "OAuth 2.0 Client ID from developer.x.com").option("--client-secret <secret>", "OAuth 2.0 Client Secret (omit to enter securely via prompt)").option("--label <label>", "Optional name for the app").option("--json", "Output raw JSON").action(async (opts) => {
553
+ const client = getClient();
554
+ try {
555
+ let clientSecret = opts.clientSecret;
556
+ if (!clientSecret) {
557
+ clientSecret = await readSecretFromStdin("Client Secret: ");
558
+ if (!clientSecret) {
559
+ error("Client secret is required");
560
+ process.exit(1);
561
+ }
562
+ }
563
+ const result = await client.setXKeys({
564
+ client_id: opts.clientId,
565
+ client_secret: clientSecret,
566
+ ...opts.label ? { label: opts.label } : {}
567
+ });
568
+ if (opts.json) {
569
+ json(result);
570
+ } else {
571
+ success("X developer keys saved.");
572
+ info(`Add this callback URI to your X app: ${result.redirect_uri}`);
573
+ info(`Required scopes: ${result.required_scopes.join(" ")}`);
574
+ info("Then run `chirpie accounts connect-x` to move an account onto your app.");
575
+ }
576
+ } catch (err) {
577
+ error(err instanceof Error ? err.message : "Failed to save X developer keys");
578
+ process.exit(1);
579
+ }
580
+ });
581
+ xKeysCommand.command("status").description("Show whether your own X developer app is configured").option("--json", "Output raw JSON").action(async (opts) => {
582
+ const client = getClient();
583
+ try {
584
+ const status = await client.getXKeysStatus();
585
+ if (opts.json) {
586
+ json(status);
587
+ } else if (!status.configured) {
588
+ info("No X developer app configured \u2014 X accounts connect through Chirpie's app.");
589
+ info(`Callback URI to register when you add one: ${status.redirect_uri}`);
590
+ } else {
591
+ success(
592
+ `Using your own X developer app${status.label ? ` (${status.label})` : ""}${status.client_id_last4 ? `, client ID ending \u2026${status.client_id_last4}` : ""}.`
593
+ );
594
+ info(`Callback URI: ${status.redirect_uri}`);
595
+ }
596
+ } catch (err) {
597
+ error(err instanceof Error ? err.message : "Failed to read X developer keys status");
598
+ process.exit(1);
599
+ }
600
+ });
601
+ xKeysCommand.command("remove").description("Remove your own X developer app credentials").option("--json", "Output raw JSON").action(async (opts) => {
602
+ const client = getClient();
603
+ try {
604
+ const result = await client.removeXKeys();
605
+ if (opts.json) {
606
+ json(result);
607
+ } else {
608
+ success(result.message);
609
+ }
610
+ } catch (err) {
611
+ error(err instanceof Error ? err.message : "Failed to remove X developer keys");
612
+ process.exit(1);
613
+ }
614
+ });
551
615
  var comingSoonCli = [
552
616
  { cmd: "connect-reddit", label: "Reddit" },
553
617
  { cmd: "connect-pinterest", label: "Pinterest" },
@@ -602,7 +666,9 @@ var keysCommand = new Command8("keys").description("Manage API keys").option("--
602
666
  id: k.id.slice(0, 8),
603
667
  name: k.name,
604
668
  prefix: k.key_prefix,
605
- revoked: k.revoked ? "\u2717" : "",
669
+ // GET /v1/keys only ever returns live keys, so there is no
670
+ // revoked column to show.
671
+ expires: k.expires_at?.slice(0, 10) ?? "never",
606
672
  last_used: k.last_used_at?.slice(0, 10) ?? "never"
607
673
  }))
608
674
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chirpie",
3
- "version": "1.0.14",
3
+ "version": "1.0.16",
4
4
  "description": "Chirpie CLI — post to social media from the command line",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,8 @@
20
20
  ],
21
21
  "scripts": {
22
22
  "build": "tsup",
23
- "dev": "tsup --watch"
23
+ "dev": "tsup --watch",
24
+ "typecheck": "tsc --noEmit"
24
25
  },
25
26
  "keywords": [
26
27
  "chirpie",
@@ -45,7 +46,7 @@
45
46
  ],
46
47
  "license": "MIT",
47
48
  "dependencies": {
48
- "@chirpie/sdk": "^1.0.12",
49
+ "@chirpie/sdk": "^1.0.14",
49
50
  "commander": "^13"
50
51
  },
51
52
  "devDependencies": {