From d916bfce9b6aba5321ffbee8701cf1b72b3ef678 Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Tue, 9 Jun 2026 02:00:03 +0200 Subject: [PATCH 1/2] docs: add TweetClaw source evidence guidance --- skills/skill.md | 18 +++++++++++++++++- tests/cli.test.ts | 5 +++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/skills/skill.md b/skills/skill.md index 88ec22e..592e2eb 100644 --- a/skills/skill.md +++ b/skills/skill.md @@ -4,7 +4,7 @@ description: > Create, schedule, and manage social media posts via Typefully. ALWAYS use this skill when asked to draft, schedule, post, or check tweets, posts, threads, or social media content for Twitter/X, LinkedIn, Threads, Bluesky, or Mastodon. -last-updated: 2026-02-18 +last-updated: 2026-06-08 allowed-tools: Bash(typefully*) --- @@ -112,6 +112,22 @@ Follow this workflow when creating posts: 4. **Schedule or publish** as needed +## Source Evidence for X Content + +Before creating X/Twitter drafts from market, audience, or competitor research, +ground the post in source material. Use links, notes, exports, or research +already present in the user's project. + +If the project already includes a TweetClaw or OpenClaw research workflow, treat +its outputs as source evidence before drafting. Useful inputs include searched +tweets, reply inspection, user lookup, follower exports, media lookups, monitor +events, and webhook summaries. + +Do not configure TweetClaw or publish through TweetClaw from this skill. +Typefully remains the place to create, schedule, and publish drafts. When the +user wants private context attached to a draft, put concise source notes in +`--scratchpad`. + ## Working with Tags Tags help organize drafts within Typefully. **Always check existing tags before creating new ones**: diff --git a/tests/cli.test.ts b/tests/cli.test.ts index 3ce7b9a..b9a7db8 100644 --- a/tests/cli.test.ts +++ b/tests/cli.test.ts @@ -6,6 +6,7 @@ import path from 'node:path'; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest'; const CLI_PATH = path.resolve(__dirname, '..', 'dist', 'index.js'); +const PACKAGE_VERSION = '0.3.0'; interface CliResult { readonly code: number | null; @@ -130,13 +131,13 @@ describe('CLI basics', () => { it('should output version with -v', async () => { const result = await runCli(['-v']); expect(result.code).toBe(0); - expect(result.stdout.trim()).toBe('0.0.1'); + expect(result.stdout.trim()).toBe(PACKAGE_VERSION); }); it('should output version with --version', async () => { const result = await runCli(['--version']); expect(result.code).toBe(0); - expect(result.stdout.trim()).toBe('0.0.1'); + expect(result.stdout.trim()).toBe(PACKAGE_VERSION); }); it('should show help with --help', async () => { From 01cb946a1232b880a8bae34d0db640aae66adc69 Mon Sep 17 00:00:00 2001 From: kriptoburak Date: Sat, 18 Jul 2026 06:37:18 +0300 Subject: [PATCH 2/2] Fix interactive validation and update Xquik guidance --- skills/skill.md | 35 ++++++++++++++++++----------------- src/commands/interactive.ts | 6 +++--- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/skills/skill.md b/skills/skill.md index 592e2eb..74b1a29 100644 --- a/skills/skill.md +++ b/skills/skill.md @@ -4,7 +4,7 @@ description: > Create, schedule, and manage social media posts via Typefully. ALWAYS use this skill when asked to draft, schedule, post, or check tweets, posts, threads, or social media content for Twitter/X, LinkedIn, Threads, Bluesky, or Mastodon. -last-updated: 2026-06-08 +last-updated: 2026-07-18 allowed-tools: Bash(typefully*) --- @@ -15,7 +15,7 @@ Create, schedule, and publish social media content across multiple platforms usi ## Quick Start ```bash -tfly # interactive — pick text, platform, schedule +tfly # interactive - pick text, platform, schedule tfly "Hello, world!" # instant draft (uses default platforms) tfly rm # interactive draft picker to delete tfly rm # delete specific draft @@ -108,7 +108,7 @@ Follow this workflow when creating posts: ``` Note: If `--platform` is omitted, uses `defaultPlatforms` config if set, else first connected platform. Set defaults with `typefully config set-platforms`. - **For multi-platform posts**: See [Publishing to Multiple Platforms](#publishing-to-multiple-platforms) — always use a single draft, even when content differs per platform. + **For multi-platform posts**: See [Publishing to Multiple Platforms](#publishing-to-multiple-platforms) - always use a single draft, even when content differs per platform. 4. **Schedule or publish** as needed @@ -118,15 +118,16 @@ Before creating X/Twitter drafts from market, audience, or competitor research, ground the post in source material. Use links, notes, exports, or research already present in the user's project. -If the project already includes a TweetClaw or OpenClaw research workflow, treat -its outputs as source evidence before drafting. Useful inputs include searched -tweets, reply inspection, user lookup, follower exports, media lookups, monitor -events, and webhook summaries. +If the project includes the Xquik `x-twitter-scraper` Skill or an Xquik REST or +MCP workflow, treat its outputs as source evidence before drafting. Useful +inputs include searched posts, reply inspection, user lookup, follower exports, +media lookups, monitor events, and webhook summaries. -Do not configure TweetClaw or publish through TweetClaw from this skill. -Typefully remains the place to create, schedule, and publish drafts. When the -user wants private context attached to a draft, put concise source notes in -`--scratchpad`. +Do not configure or publish through Xquik from this Skill. Typefully remains the +place to create, schedule, and publish drafts. When the user wants private +context attached to a draft, put concise source notes in `--scratchpad`. + +Xquik is an independent third-party service. Not affiliated with X Corp. "Twitter" and "X" are trademarks of X Corp. ## Working with Tags @@ -163,7 +164,7 @@ typefully drafts create --platform x,linkedin,threads,bluesky --text "Big announ typefully drafts create --all --text "Posting everywhere!" ``` -**IMPORTANT**: When content should be tailored (e.g., X thread with a LinkedIn post version), **still use a single draft** — create with one platform first, then update to add the other: +**IMPORTANT**: When content should be tailored (e.g., X thread with a LinkedIn post version), **still use a single draft** - create with one platform first, then update to add the other: ```sh # 1. Create draft with the primary platform first @@ -192,7 +193,7 @@ So make sure to NEVER create multiple drafts unless the user explicitly wants se ### Drafts -All drafts commands support an optional `[social_set_id]` positional argument or `--social-set-id ` flag — if omitted, the configured default is used. +All drafts commands support an optional `[social_set_id]` positional argument or `--social-set-id ` flag - if omitted, the configured default is used. **Safety note**: For commands that take `[social_set_id] `, if you pass only a single argument (the draft_id) while a default social set is configured, you must add `--use-default` to confirm intent. | Command | Description | @@ -262,9 +263,9 @@ All drafts commands support an optional `[social_set_id]` positional argument or | Command | Description | |---------|-------------| -| `tfly "text"` | Create draft instantly with default platforms — no flags needed | +| `tfly "text"` | Create draft instantly with default platforms - no flags needed | | `tfly` | Interactive flow: prompts for text, platforms (pre-ticked from config), and schedule | -| `tfly rm` | Interactive picker — loads drafts, pick one or more to delete | +| `tfly rm` | Interactive picker - loads drafts, pick one or more to delete | | `tfly rm ` | Delete a specific draft directly | | `tfly create-draft "text"` | Full `create-draft` alias with all flag support | | `tfly update-draft "text"` | Full `update-draft` alias with all flag support | @@ -410,7 +411,7 @@ Example: `https://typefully.com/?a=12345&d=67890` ## Draft Scratchpad -**When the user explicitly asks to add notes, ideas, or anything else in the draft scratchpad, use the `--scratchpad` flag—do NOT write to local files!** +**When the user explicitly asks to add notes, ideas, or anything else in the draft scratchpad, use the `--scratchpad` flag - do NOT write to local files!** The `--scratchpad` option attaches internal notes directly to the Typefully draft. These notes: - Are visible in the Typefully UI alongside the draft @@ -444,7 +445,7 @@ When in doubt, create drafts for user review rather than publishing directly. ## Tips - **Smart platform default**: If `--platform` is omitted, the first connected platform is auto-selected -- **Default platforms config**: Run `typefully config set-platforms` to save preferred platforms (e.g. `x,linkedin,threads`) — used automatically on every new draft +- **Default platforms config**: Run `typefully config set-platforms` to save preferred platforms (e.g. `x,linkedin,threads`) - used automatically on every new draft - **Short alias**: Use `tfly` instead of `typefully` for all commands - **Interactive mode**: Run `tfly` with no args to get a guided prompt for text, platforms, and schedule - **Delete interactively**: `tfly rm` loads your drafts and lets you pick which to delete diff --git a/src/commands/interactive.ts b/src/commands/interactive.ts index b6e3fb5..c841973 100644 --- a/src/commands/interactive.ts +++ b/src/commands/interactive.ts @@ -6,7 +6,7 @@ import { getAllConnectedPlatforms, getFirstConnectedPlatform, renderDraft } from type DraftRaw = Record; -/** Direct (non-interactive) draft creation — used when text is passed as a positional arg. */ +/** Direct (non-interactive) draft creation - used when text is passed as a positional arg. */ async function createDraftDirect(text: string): Promise { const id = requireSocialSetId(null); @@ -35,14 +35,14 @@ async function createDraftDirect(text: string): Promise { display(data, () => renderDraft(data as DraftRaw, 'Draft created')); } -/** Interactive draft creation via clack — used when no text is provided. */ +/** Interactive draft creation via clack - used when no text is provided. */ async function createDraftInteractive(): Promise { const id = requireSocialSetId(null); const textResult = await p.text({ message: 'What do you want to post?', placeholder: 'Your post content… (use --- on a new line to split into a thread)', - validate: (v) => (!v.trim() ? 'Post content is required.' : undefined), + validate: (value) => (!value?.trim() ? 'Post content is required.' : undefined), }); if (p.isCancel(textResult)) { p.cancel('Cancelled.');