Skip to content

Repository files navigation

InPost

InPost

Multi-notebook to LinkedIn publishing pipeline with AI-powered content transformation.

InPost fetches blog posts from Notion, Obsidian, OneNote, or Evernote, transforms them into LinkedIn-optimized content using AI, and publishes them via the LinkedIn API — all from the command line.

Features

Multi-Notebook Support

  • Fetch content from Notion, Obsidian, OneNote, or Evernote
  • Switch providers with --notebook <provider> or shorthand flags (--notion, --obsidian, etc.)
  • Set a default provider via DEFAULT_NOTEBOOK in .env

Automated Pipeline

  • Fetch Notion pages marked "Ready"
  • Convert Notion blocks to LinkedIn-compatible text
  • Publish to LinkedIn via API
  • Update Notion with LinkedIn URL + published status
  • Log analytics and errors

AI Content Transformation

  • Blog → LinkedIn summary
  • Attention-grabbing hooks
  • Tone rewriting (professional, casual, authority, storytelling, educational)
  • Auto-generated hashtags
  • Thread splitting for long content
  • Multiple post variants

Multi-Provider AI Support

  • Groq (recommended) — 14,400 free requests/day
  • Google Gemini — Free tier available
  • Anthropic Claude — Paid

Prerequisites

Quick Start

# Copy and fill in your credentials
cp .env.example .env
# Edit .env with your API keys (see Configuration below)# Install, build, and link globally
./setup.sh
# Check your configuration
inpost status
# Authenticate with LinkedIn
inpost auth
# Transform content from any provider
inpost transform "Your blog content here"
inpost transform --notion-title "My Post" -i
inpost transform --obsidian-title "My Note" -i --save
inpost transform --onenote-title "My Page" -i --save
inpost transform --evernote-title "My Note" -i --save
# Publish to LinkedIn
inpost publish "Your LinkedIn post text"
inpost publish --obsidian-title "My Note"# Full pipeline: fetch → transform → publish
inpost pipeline --dry-run
# Get help for any command
inpost transform ?
inpost schedule ?

Commands

CommandDescription
inpost transform [text]Transform content for LinkedIn
inpost publish [text]Publish content to LinkedIn
inpost pipelineFull pipeline: fetch → transform → publish
inpost fetchFetch posts from Notion by status
inpost queueShow the next posts in the publishing queue
inpost authAuthenticate with LinkedIn (or OneNote) via OAuth
inpost scheduleRun pipeline on a cron schedule
inpost statusCheck configuration and connection status

Append ? to any command for contextual help, e.g. inpost transform ?.

Transform

inpost transform "Your content here"
inpost transform --notion-id <id>
inpost transform --notion-title "My Post"
inpost transform --file ./post.txt
# Other note providers
inpost transform --obsidian-title "My Note"
inpost transform --onenote-title "My Page"
inpost transform --evernote-title "My Note"# Interactive mode - refine with feedback
inpost transform "Your content" -i
Options:
-t, --tone <tone> Tone (defaults to DEFAULT_TONE in .env)
-i, --interactive Refine output with feedback loop
--variants <count> Number of variants to generate
--hooks Generate attention-grabbing hooks
--hashtags Auto-generate hashtags
--thread Split into LinkedIn thread
--save Save result back to the note source
--json Output as JSON
--notebook <provider> notion | obsidian | onenote | evernote
--notion | --obsidian | --onenote | --evernote Provider shorthands
--title <title> Note title (used with --notebook)
--id <id> Note ID (used with --notebook)

Interactive mode lets you refine the output:

  1. View the generated post
  2. Choose: Accept, Provide feedback, Regenerate, Help, or Cancel
  3. If feedback: describe changes (e.g., "make it shorter", "add a question")
  4. Review the refined version
  5. Repeat until satisfied

Publish

inpost publish "Your LinkedIn post"
inpost publish --notion-id <id>
inpost publish --obsidian-title "My Note"
inpost publish --onenote-title "My Page"
inpost publish --evernote-title "My Note"
Options:
--dry-run Preview without posting
--connections Limit visibility to connections only
--no-update-notion Skip updating Notion after publishing
--notebook <provider> notion | obsidian | onenote | evernote
--notion | --obsidian | --onenote | --evernote Provider shorthands
--title <title> Note title (used with --notebook)
--id <id> Note ID (used with --notebook)

Pipeline

inpost pipeline
inpost pipeline --dry-run
Options:
--status <value> Notion status to fetch (default: "Ready")
--limit <number> Maximum posts to process (default: 5)
--tone <tone> Default tone for AI transformation
--hooks Include hooks in generated content
--hashtags Include hashtags
--dry-run Run everything except actual LinkedIn publish
--no-confirm Skip confirmation prompts
--notebook <provider> notion | obsidian | onenote | evernote
--order <order> oldest | newest (overrides PIPELINE_ORDER in .env)

Fetch

inpost fetch
inpost fetch --status Ready
inpost fetch --all --limit 20
# Fetch from a specific provider
inpost fetch --obsidian --all
inpost fetch --notebook onenote --all
Options:
--status <value> Status filter (default: "Ready")
--limit <number> Max results to return
--all List all posts regardless of status
--notebook <provider> notion | obsidian | onenote | evernote
--notion | --obsidian | --onenote | --evernote Provider shorthands

Queue

Show the next posts in the publishing queue — Ready status, oldest first. This matches the order the pipeline will process them.

inpost queue # next 10 (default)
inpost queue --limit 5 # next 5
Options:
--limit <number> Max posts to show (default: 10)
--output <format> table | json | quiet (default: table)

Schedule

inpost schedule
inpost schedule --once
inpost schedule --cron "0 9 * * 1-5" --timezone "America/New_York"
inpost schedule --limit 2
Options:
--once Run immediately instead of on a schedule
--cron <expression> Cron expression (overrides SCHEDULE_CRON in .env)
--timezone <tz> Timezone (overrides SCHEDULE_TIMEZONE in .env)
--limit <number> Max posts per run (overrides SCHEDULE_LIMIT in .env)
--order <order> oldest | newest (overrides PIPELINE_ORDER in .env)

Auth

inpost auth # Authenticate with LinkedIn
inpost auth --onenote # Authenticate with Microsoft (OneNote)

Note Providers

InPost supports four note sources. See docs/note-providers.md for full setup instructions.

ProviderAuthSetup
NotionAPI tokendocs/notion-setup.md
ObsidianNone — reads local vault filesdocs/obsidian-setup.md
OneNoteOAuth via Azure ADdocs/onenote-setup.md
EvernoteDeveloper tokendocs/evernote-setup.md

Provider flag reference

All provider flags work identically across transform, publish, fetch, pipeline, and status.

FlagProvider
--notion-title <title> / --notion-id <id>Notion
--obsidian-title <title> / --obsidian-id <path>Obsidian
--onenote-title <title> / --onenote-id <id>OneNote
--evernote-title <title> / --evernote-id <guid>Evernote

Configuration

Environment Variables

# Required: Notion (if using Notion)
NOTION_API_TOKEN=ntn_xxx
NOTION_DATABASE_ID=xxx-xxx-xxx
# Required: AI Provider (set at least one)
GROQ_API_KEY=gsk_xxx # Recommended - best free tier
GEMINI_API_KEY=AIza_xxx # Free tier available
ANTHROPIC_API_KEY=sk-ant-xxx # Paid# Required for publishing: LinkedIn
LINKEDIN_CLIENT_ID=xxx
LINKEDIN_CLIENT_SECRET=xxx
# Optional
DEFAULT_TONE=professional
LOG_LEVEL=info
DEFAULT_NOTEBOOK=notion # notion | onenote | obsidian | evernote# Scheduler
SCHEDULE_CRON=30 9 ** 1 # Default: Mondays at 09:30 UTC
SCHEDULE_TIMEZONE=Europe/London
SCHEDULE_LIMIT=1 # Max posts per scheduled run
PIPELINE_ORDER=oldest # oldest | newest — which ready posts to pick first# Obsidian (no API key needed)
OBSIDIAN_VAULT_PATH=/Users/you/Documents/MyVault
OBSIDIAN_NOTES_DIR=Blog Posts # optional — scope to a subdirectory# OneNote (requires Azure AD app)
ONENOTE_CLIENT_ID=
ONENOTE_CLIENT_SECRET=
ONENOTE_TENANT_ID=consumers
ONENOTE_REDIRECT_URI=http://localhost:3456/callback
# Evernote (requires developer token)
EVERNOTE_TOKEN=
EVERNOTE_NOTEBOOK= # optional — scope to a specific notebook
EVERNOTE_SANDBOX=false

AI Provider Priority

InPost auto-selects the AI provider based on available keys:

  1. Groq (if GROQ_API_KEY set) — Fastest, best free tier
  2. Gemini (if GEMINI_API_KEY set) — Good free tier
  3. Anthropic (if ANTHROPIC_API_KEY set) — Highest quality, paid

Notion Database Setup

Your Notion database needs these properties:

PropertyTypePurpose
NameTitlePost title
StatusSelectDraft / Ready / Transforming / Publishing / Published / Error
LinkedIn URLURLFilled after publishing
Published DateDateFilled after publishing
ToneSelectAI tone override per post
TagsMulti-selectFor hashtag generation
AI SummaryRich textAI-generated LinkedIn post
VariantsRich textMultiple post variants
Error LogRich textError details

See docs/notion-setup.md for full setup instructions.

Development

npm run dev -- status # Run in dev mode
npm test# Run unit tests
npm run test:watch # Watch mode
npm run typecheck # Type checking
npm run lint # Lint

License

MIT

About

Notion to LinkedIn publishing pipeline with AI-powered content transformation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages