Transform meeting transcripts and notes into engaging social media posts with AI
shippost is a human-in-the-loop CLI tool that processes your content into social media post ideas. Keep your workflow local and private with Ollama, or leverage Anthropic Claude for enhanced quality.
CLI command: ship
- Why shippost?
- Quick Start
- Commands
- Configuration
- Content Strategies
- Typefully Integration
- X (Twitter) Integration
- Customizing Prompts
- Community Style Examples
- Tips & Best Practices
- Troubleshooting
- Development
| Feature | shippost | Manual Writing | Other Tools |
|---|---|---|---|
| Privacy | Local LLM support (Ollama) | ✓ | Cloud-only |
| Human-in-the-loop | Review before posting | ✓ | Often auto-posts |
| Style consistency | Learns your voice | Manual effort | Generic |
| Content strategies | 64 proven formats | Ad-hoc | Limited |
| Integrations | Typefully + X API | N/A | Varies |
- Flexible LLM Providers — Ollama (local, private) or Claude (cloud, high-quality)
- 64 Content Strategies — Proven post formats for maximum variety
- Customizable Style — Define your brand voice in editable prompt files
- X Post Analysis — Auto-generate style guides from your existing tweets
- Reply Guy Mode — Find and reply to tweets from your timeline
- Typefully Integration — Stage posts directly as drafts
- Banger Scoring — Each post scored 1-99 for viral potential
- Node.js >= 18.0.0
- LLM Provider (choose one):
- Ollama — Local, free, private
- Anthropic Claude — Cloud, paid, high-quality
git clone <repo-url>
cd shippost
npm install && npm run build
npm link # Makes 'ship' command available globally# Initialize a new project
ship init
# Add your content
cp ~/meeting-notes.txt input/
# Generate posts
ship work
# Review generated posts, then stage approved posts to Typefully
ship reviewThat's it! Your posts are in posts.jsonl, ready for review.
| Command | Description |
|---|---|
ship init |
Initialize project structure |
ship work |
Generate posts from input files |
ship posts |
View generated posts |
ship ui |
Local web app for the whole pipeline |
ship review |
Interactively approve/reject generated posts |
ship analyze-x |
Generate style guide from your tweets |
ship reply |
Find and post replies on X |
ship x-status |
Check X API rate limits |
ship stats |
X metrics dashboard (Basic tier) |
ship sync-prompts |
Update prompts to latest defaults |
Initialize a new ship project in the current directory.
Creates:
| Path | Description |
|---|---|
.shippostrc.json |
Project configuration |
input/ |
Directory for source content |
prompts/style.md |
Your posting style and voice |
prompts/work.md |
Post generation instructions |
prompts/system.md |
System prompt (advanced) |
prompts/analysis.md |
Style analysis prompt (advanced) |
prompts/content-analysis.md |
Strategy selection (advanced) |
prompts/banger-eval.md |
Viral scoring criteria (advanced) |
prompts/reply.md |
Reply analysis (advanced) |
strategies.json |
Customizable content strategies |
Process all files in input/ and generate posts.
# Basic usage (auto-selects 8 diverse strategies)
ship work
# List available strategies
ship work --list-strategies
ship work --list-strategies --category educational
# Use specific strategies
ship work --strategy personal-story
ship work --strategies "how-to-guide,bold-observation,resource-list"
# More options
ship work --count 12 # Generate 12 posts per file
ship work --model llama3.1 # Use specific model
ship work --force # Reprocess all files
ship work --verbose # Detailed output
ship work --no-strategies # Legacy mode (no strategies)Options:
--target <social|blog|revisions>— Select output (default: social)--sync— Explicitly sync Granola before generation-m, --model <model>— Override the LLM model-v, --verbose— Show detailed processing info-f, --force— Force reprocessing for the selected target-c, --count <n>— Posts to generate per file (default: 8)-s, --strategy <id>— Use specific strategy--strategies <ids>— Multiple strategies (comma-separated)--list-strategies— List all strategies--category <name>— Filter strategies by category--no-strategies— Disable strategy system
How it works:
- Validates environment (LLM provider, required files)
- Loads your style guide and instructions
- Scans
input/for.txtand.mdfiles - Skips already-processed files (use
--forceto override) - Generates posts using selected strategies
- Scores each post for viral potential
- Saves to
posts.jsonl
Note: Tracking in
.shippost-state.jsonprevents repeated generation per source and target. Use--forceto explicitly regenerate modified inputs.
View generated posts with filtering options.
ship posts # Last 10 posts
ship posts -n 20 # Last 20 posts
ship posts --strategy "personal-story"
ship posts --min-score 70 # High-quality only
ship posts --source "meeting" # Filter by source file
ship posts --eval # Score posts missing scoresOptions:
-n, --count <n>— Number of posts to show (default: 10)--strategy <name>— Filter by strategy--min-score <n>— Minimum banger score--source <text>— Filter by source filename--eval— Evaluate unscored posts
Local web app (http://127.0.0.1:4747) covering the whole pipeline in five tabs. ship review --web opens the same app.
ship ui # Start the app and open the browser
ship ui --port 5000 # Custom port
ship ui --min-score 60 # Filter the review queueTabs:
- Generate — card per unprocessed transcript with attendees and a one-line summary;
pprocess /kskip. Processing queues sequentially with a live status line; skips persist. - Review — score-sorted queue;
aapprove,rreject,eedit,kskip,⌘sapprove while editing. Select text and hittabto have the LLM rewrite just that span in your voice. Edits persist per post until decided. Typefully staging is a separate action for approved posts. - Reply — scan your timeline for reply opportunities, edit inline, post + like or skip.
- Stats — account tiles, 7-day metrics, 90-day goal progress, top post.
- Unfollow — candidates ranked by LLM relevance to your interests plus quality signals, protected by a feed-presence check and a whitelist. Unfollow decisions persist to disk and retry automatically if you hit X API limits.
The server is localhost-only. Jobs (generation, scans, unfollows) run server-side, so you can close the tab and come back.
Interactively review posts and approve or reject them. Approved posts can be staged to Typefully from ship ui after content review.
ship review # Review all new posts
ship review --min-score 70 # Only high-quality postsActions during review:
a— Approve for stagingr— Rejectq— Quit
Post statuses:
new— Not yet reviewedkeep— Saved for laterapproved— Content-reviewed and ready to stagestaged— Sent to Typefullyrejected— Filtered outpublished— Reserved for future
Generate a personalized style guide by analyzing your X posts.
ship analyze-x # Analyze 33 tweets (default)
ship analyze-x --count 100 # More tweets for deeper analysis
ship analyze-x --overwrite # Replace existing analysis
ship analyze-x --setup # Reconfigure X API credentialsRequirements:
- Free X Developer account (sign up)
- OAuth 2.0 app with redirect URI:
http://127.0.0.1:9876/callback - Scopes:
tweet.read,users.read,offline.access
First-time setup:
- Create app at X Developer Portal
- Enable OAuth 2.0
- Set redirect URI to
http://127.0.0.1:9876/callback - Run
ship analyze-xand enter your Client ID
Rate limits: Free tier allows 100 reads/month. Upgrade to Basic ($200/month) for 10,000 reads.
Find tweets from accounts you follow and generate contextual replies.
ship reply # Analyze 10 tweets
ship reply --count 20 # Analyze more tweetsActions during review:
Enter— Post the replye— Edit before postingn— Skip this tweetq— Quit
Requirements:
- Same X API setup as
ship analyze-x - App must have "Read and Write" permissions
- Additional scope:
tweet.write
Basic tier features ($200/month): Tweets sorted by author follower count, shows engagement metrics.
Check X API rate limits and account info.
ship x-statusShows: connected account, API tier, rate limit status with progress bars, and reset times.
Comprehensive X metrics dashboard. Requires X API Basic tier ($200/month).
ship statsShows: follower counts, posting activity, impressions with sparklines, 90-day goal progress, engagement metrics, best posting times, and top performing posts.
Update local prompts to latest package defaults.
ship sync-prompts # Interactive update
ship sync-prompts --force # Update all without promptingConfiguration is stored in .shippostrc.json.
{
"llm": {
"provider": "ollama"
},
"ollama": {
"host": "http://127.0.0.1:11434",
"model": "llama3.1",
"timeout": 60000
},
"generation": {
"postsPerTranscript": 8,
"temperature": 0.7,
"strategies": {
"enabled": true,
"autoSelect": true,
"diversityWeight": 0.7,
"preferThreadFriendly": false
}
}
}{
"llm": {
"provider": "anthropic"
},
"anthropic": {
"model": "claude-sonnet-5-5",
"maxTokens": 4096
},
"generation": {
"postsPerTranscript": 8
},
"typefully": {
"socialSetId": "1"
}
}Set API keys in .env:
ANTHROPIC_API_KEY=sk-ant-api03-your-key-here
TYPEFULLY_API_KEY=your-typefully-api-key-hereSee ANTHROPIC_SETUP.md for detailed Claude setup.
| Option | Default | Description |
|---|---|---|
llm.provider |
ollama |
ollama or anthropic |
ollama.host |
http://127.0.0.1:11434 |
Ollama server URL |
ollama.model |
llama3.1 |
Ollama model |
ollama.timeout |
60000 |
Request timeout (ms) |
anthropic.model |
claude-sonnet-5-5 |
Claude model |
anthropic.maxTokens |
4096 |
Max response tokens |
generation.postsPerTranscript |
8 |
Posts per input file |
generation.temperature |
0.7 |
Sampling (0.0-1.0); omitted for newer Claude models |
generation.strategies.enabled |
true |
Enable strategies |
generation.strategies.autoSelect |
true |
Auto-select strategies |
generation.strategies.diversityWeight |
0.7 |
Category diversity (0.0-1.0) |
generation.strategies.preferThreadFriendly |
false |
Prefer thread strategies |
x.clientId |
— | X API OAuth Client ID |
x.apiTier |
free |
free or basic |
typefully.socialSetId |
"1" |
Typefully Social Set ID |
shippost includes 64 proven content strategies inspired by Typefully's successful formats. Each strategy provides a unique angle for presenting your ideas.
Instead of generic posts, shippost applies specific frameworks:
- Personal Story — Share experiences and transformations
- How-To Guide — Step-by-step instructions
- Bold Observation — Provocative statements that capture attention
- Before & After — Show transformation or progress
- Resource Thread — Curate valuable tools or links
- Behind-the-Scenes — Show your process
| Category | Description |
|---|---|
| Personal | Stories, experiences, transformations |
| Educational | How-tos, frameworks, tips |
| Provocative | Bold statements, contrarian takes |
| Engagement | Questions, polls, thought experiments |
| Curation | Lists, recommendations, resources |
| Behind-the-Scenes | Process, WIP, building |
| Reflective | Lessons learned, retrospectives |
- Content Analysis — Analyzes your transcript for characteristics (personal stories, actionable advice, strong opinions)
- Strategy Selection — Selects applicable strategies ensuring category diversity
- Post Generation — Each post follows one strategy's format
Edit strategies.json to add, modify, or remove strategies:
{
"id": "weekly-reflection",
"name": "Weekly Reflection Post",
"prompt": "Share a key lesson from this week. What did you learn?",
"category": "reflective",
"threadFriendly": false,
"applicability": {
"worksWithAnyContent": true
}
}Applicability flags:
requiresPersonalNarrative— Needs personal storiesrequiresActionableKnowledge— Needs how-to contentrequiresResources— Needs tool/book mentionsrequiresProject— Needs project contextrequiresStrongOpinion— Needs strong viewpointsworksWithAnyContent— Always applicable
Stage posts directly to Typefully drafts.
- Get API key: Typefully → Settings → Integrations
- Add to
.env:TYPEFULLY_API_KEY=your-api-key-here
- (Optional) Configure Social Set ID for multi-account setups
# Review posts and approve the best ones
ship review --min-score 70
# Stage approved posts from the web UI
ship uiApprove posts during review, then use the Review tab's "Stage next approved" button to create Typefully drafts. The draft URL is displayed for quick access.
Note: Posts are created as drafts, not published. Requires Typefully Pro plan.
- Create app at X Developer Portal
- Enable OAuth 2.0
- Set redirect URI:
http://127.0.0.1:9876/callback - For
ship reply: Enable "Read and Write" permissions
| Feature | Free | Basic ($200/mo) |
|---|---|---|
| Analyze tweets | ✓ (100/mo) | ✓ (10,000/mo) |
| Post replies | ✓ | ✓ |
| Follower counts | — | ✓ |
| Sort by influence | — | ✓ |
| Stats dashboard | — | ✓ |
Configure tier in .shippostrc.json:
{
"x": {
"clientId": "your-client-id",
"apiTier": "basic"
}
}- Free tier: ~15 requests per 15 minutes
- Use
--count 10or less forship reply - Check status with
ship x-status
All prompts are stored as editable markdown files in prompts/.
| File | Purpose | When to Edit |
|---|---|---|
style.md |
Brand voice, tone, examples | Voice not right, want different tone |
work.md |
Generation instructions | Posts need different structure |
| File | Purpose |
|---|---|
system.md |
System prompt wrapper |
analysis.md |
X post style analysis |
content-analysis.md |
Strategy selection criteria |
banger-eval.md |
Viral scoring criteria |
reply.md |
Reply opportunity analysis |
- No code changes — Customize by editing markdown
- Version controlled — Track prompt changes in git
- Project-specific — Each project can have unique prompts
Learn from real style.md files in community-examples/style/.
# Browse examples
ls community-examples/style/
# Use as starting point
cp community-examples/style/example-technical-founder.md prompts/style.mdShare your style.md:
- Copy to
community-examples/style/your-name.md - Remove sensitive information
- Add context at the top
- Submit a PR
- Use well-structured transcripts with clear sections
- Remove filler words for better results
- Longer transcripts (500+ words) generate better insights
Ollama:
llama3.1— Good balance (default)llama2— Faster iterationsmixtral— More creative
Anthropic:
claude-sonnet-5-5— Best balance (recommended)claude-haiku-4-5-20251001— Fastestclaude-opus-5-5— Complex coding and knowledge workclaude-fable-5-1— Demanding reasoning
- Let auto-selection work for most transcripts
- Use
--count 12for longer transcripts - Analyze which strategies perform best using scores
- Experiment with
diversityWeightconfig
# Filter posts with jq
cat posts.jsonl | jq 'select(.metadata.bangerScore > 70)'
# Group by strategy
cat posts.jsonl | jq -r '.metadata.strategy.category' | sort | uniq -c
# Find best strategy
cat posts.jsonl | jq -r 'select(.metadata.bangerScore > 70) | .metadata.strategy.name' | sort | uniq -c | sort -rn"Ollama is not available"
# Install from https://ollama.ai
ollama serve # Start server
curl http://localhost:11434 # Verify"Model not found"
ollama pull llama3.1"API key not found"
Add to .env:
ANTHROPIC_API_KEY=sk-ant-api03-your-key-here"API not available"
- Check API key validity
- Verify account has credits
- Check status.anthropic.com
403 errors when posting:
- Change app to "Read and write" at Developer Portal
- Delete
.shippost-tokens.json - Re-authenticate
429 rate limit errors:
- Wait 15 minutes
- Use
--count 10or less - Check
ship x-status
"Not a ship project"
ship initConfiguration errors
Ensure .shippostrc.json is valid JSON with required fields.
npm install # Install dependencies
npm run dev # Development mode
npm run build # Build TypeScript
npm link # Link globally for testingsrc/
├── index.ts # CLI entry point
├── commands/ # Command implementations
├── types/ # TypeScript types
├── services/ # LLM, X API, Typefully integrations
└── utils/ # Helpers (logging, validation, etc.)
Issues are tracked on GitHub (gh issue list). See AGENTS.md for workflow.
Posts are stored in posts.jsonl:
{
"id": "uuid",
"sourceFile": "input/meeting.txt",
"content": "Your generated post...",
"metadata": {
"model": "llama3.1",
"temperature": 0.7,
"strategy": {
"id": "personal-story",
"name": "Personal Story",
"category": "personal"
},
"bangerScore": 75,
"bangerEvaluation": {
"score": 75,
"breakdown": { "hook": 18, "emotional": 16, "..." : "..." },
"reasoning": "Strong opening hook..."
}
},
"timestamp": "2024-01-15T10:30:00.000Z",
"status": "new"
}Each post is scored 1-99 for viral potential:
| Score | Potential |
|---|---|
| 1-29 | Low |
| 30-49 | Below average |
| 50-69 | Average |
| 70-84 | High |
| 85-99 | Exceptional |
Scoring factors:
- Hook Strength (20 pts)
- Emotional Resonance (20 pts)
- Value & Shareability (15 pts)
- Format & Structure (15 pts)
- Relevance & Timing (10 pts)
- Engagement Potential (10 pts)
- Authenticity & Voice (10 pts)
Granola is an AI meeting transcription tool.
- Manual Copy: Click transcription button → copy →
pbpaste > input/meeting.txt - Chrome Extension: Granola Transcriber
- Raycast Extension: Granola for Raycast (bulk export)
- Use descriptive filenames:
YYYY-MM-DD-topic.txt - Clean transcripts before exporting for better quality
- Batch process multiple meetings at once
-
ship init,ship work,ship posts,ship review -
ship analyze-x,ship reply,ship x-status,ship stats - Typefully integration
- 64 content strategies
- Banger scoring
-
ship analyze— Success metrics (X Basic API) - News-aware post generation
- LinkedIn support
- Multiple output formats (CSV, Markdown)
- Bulk staging command
MIT
ship work now defaults to social posts only. It does not generate blog drafts, change articles, or sync Granola automatically. Existing flags such as --files, --all, --count, and strategy options still apply; --count controls social post generation.
ship work --target social --all --files meeting.txt
ship work --target blog --all --files meeting.txt
ship work --target revisions --all --files meeting.txt
ship work --sync --target social # explicitly sync Granola firstThe Generate tab offers Generate all 3: one click runs social posts, blog drafts, and article revision proposals sequentially. A failed output does not stop the other types; retrying runs only unfinished types. Sources stay in the queue until every type is completed or skipped. Skip applies to all types. The separate Sync Granola button imports sources. CLI target selection remains available for individual runs.
Completion is tracked per source and target in .shippost-state.json. Newly generated social posts do not prevent a later blog run. Existing records without target metadata are treated as completed for all targets to avoid silently regenerating historical content; use --force --target blog --files meeting.txt to explicitly rerun one target. A failed target stays retryable without rerunning other completed targets. Social strategy output is held until the full batch succeeds, so a model failure does not save a partial social batch. File writes and completion tracking are not a distributed transaction: inspect saved outputs after a process crash before forcing a retry.
Blog runs create new drafts and use a fresh slug when a draft, article, or cover already exists. Revision runs save proposals in local .shippost-revisions/, with the original article path, its SHA-256 hash, and the source reference in a companion JSON file. Original articles remain unchanged. Review the proposal against the original, confirm the original hash still matches, then manually apply the chosen edits and run the site's checks before publication. There is no automatic apply/publish action. Repeated or interrupted revision runs may produce multiple proposals; review them before applying.
Revision instructions live in prompts/blog-revision.md, created by ship init. For an existing workspace, copy src/templates/blog-revision.md from the Shippost checkout (or dist/templates/blog-revision.md from its package) into your workspace's prompts/ directory and customize it.
Run ship ui from the content workspace and open the Settings tab. A workspace with no local config opens Settings automatically; you do not need to run ship init or edit JSON. Saving creates missing prompts, input directory, strategies, and posts file while preserving existing editorial files. It also creates a missing revision prompt in an existing workspace.
Settings covers the LLM provider, model and server, output/token limits, temperature, strategy options, Typefully social set, X client ID/tier, and blog/image output paths. Test saved LLM connection uses the saved settings and may make a small billable provider request. Saving alone does not call a provider, stage drafts, publish content, or authorize an X account. X OAuth authorization still uses the existing ship analyze-x --setup flow; Granola API keys can be saved under Credentials.
API keys and the X client secret can be entered, replaced, or removed in the browser. They are stored in local .shippost-secrets.json with owner-only permissions, loaded by CLI commands and generation workers, and never sent back in settings responses. Blank credential fields keep existing values; explicit removal clears a saved value. Existing Anthropic keys in local config migrate to the separate credentials file on save. Both files stay ignored by Git; ignore rules do not remove files already tracked elsewhere. Environment-provided credentials and account overrides take precedence and appear as managed fields.
Changes apply on the next operation, and cached provider clients reset after saving. Settings changes are blocked while background jobs or Typefully staging are active. Settings access is restricted to the localhost origin and saves require a per-server browser token. This is a local UI, not an authenticated public deployment: use the local browser until authenticated remote access is implemented.
Anthropic model suggestions were refreshed against the current model overview on October 5, 2026: Sonnet 5.5 (new-workspace default), Opus 5.5, Fable 5.1, and Haiku 4.5. Existing explicit model choices are preserved, and you can enter another model ID. Settings hides temperature for newer or unrecognized Claude models; the request also omits it, even when an older config has a temperature value. Known compatible legacy models (including Haiku 4.5) and Ollama retain the control. Anthropic recommends omitting sampling parameters for newer models in its migration guide. Generated-post metadata omits temperature when it was not sent.
The Generate tab defaults to Past 30 days: today and the preceding 29 UTC calendar dates, using recorded meeting dates or the date prefix in imported filenames. Copying a file does not make an old meeting recent. Older, future-dated, and undated sources remain accessible through All dates. This filters the local queue; use Sync Granola to import recent notes. An empty recent queue means recent meetings may still need importing.
In Settings → Credentials, save a Granola API key with Personal notes access (Business or Enterprise plan). Then use Generate → Sync Granola. The official API importer fetches notes created within the past 30 UTC calendar dates, including private written notes and AI summaries; it does not fetch full transcripts. Notes are identified by stable Granola IDs, paginated, saved locally, and checkpointed after each successful import. Empty or failed notes stay retryable. Already imported notes are skipped; CLI --force explicitly refreshes them. API failures do not fall back to desktop credentials.
The CLI uses the same importer when GRANOLA_API_KEY is saved in the workspace or set in the environment. Without a key, the CLI retains the legacy macOS desktop importer. The UI requires an API key and does not need Granola installed on the server. Keys use the same ignored, owner-only credential file as the other integrations and are never returned to the browser.
To suspend X integration, turn off Settings → X → Enable X API access. This blocks OAuth and X API clients, including replies, unfollows, and analytics, for the workspace. Credentials and queued unfollow decisions are retained; pending decisions only run after explicit Retry. Granola imports and local content generation remain available.
Select grok in Settings to generate through the official Grok Build CLI using your Grok account. Grok Build must be installed on the computer running Shippost. Authenticate once from the workspace:
GROK_HOME="$PWD/.shippost-grok" grok login --device-authComplete the official sign-in link, save the Grok provider/model in Settings, and test the connection. The default model is grok-4.7. Grok manages its own credentials in .shippost-grok/, which Settings adds to .gitignore; this directory also contains native session state and must remain private. Shippost does not read or return the tokens. Subscription eligibility, limits, and billing are controlled by your Grok account.
Generation sends the existing editable prompts through a temporary owner-only prompt file, deletes it afterward, and disables tools, search, and subagents. This provider does not use the X/Twitter API or an inherited xAI API key. Temperature is not sent. The existing three-output workflow and per-target retries are unchanged.
References: Grok Build, headless usage, and Grok subscription usage.