An Obsidian plugin that lets you compose and publish LinkedIn posts directly from your notes. Write your thoughts in a note, hit a command, and it's posted — no switching apps.
- Note-based workflow: Each LinkedIn post is an Obsidian note with frontmatter tracking metadata
- URL sharing: Paste a URL and the plugin fetches the page title, creates a note, and attaches the link as a LinkedIn article preview
- Text-only posts: Skip the URL for thought-leadership posts
- Preview before posting: See exactly what will be published, with character count (3,000 max)
- Markdown conversion: Automatically converts Obsidian Markdown to LinkedIn-compatible formatting
- Frontmatter tracking: Status, post date, LinkedIn URL, tags, and visibility are all tracked per-note
- Secure token storage: OAuth tokens stored in Obsidian's SecretStorage (not in your vault files)
- Auto token refresh: Access tokens are refreshed automatically before they expire
- Download the latest release (or build from source — see below)
- Copy
main.js,manifest.json, andstyles.cssinto your vault at.obsidian/plugins/linkedin-poster/ - In Obsidian, go to Settings → Community plugins and enable LinkedIn Poster
git clone https://github.com/scottaw66/obsidian-linkedin-poster.git
cd obsidian-linkedin-poster
bun install # or npm install
bun run build # or npm run buildThen copy main.js, manifest.json, and styles.css to your vault's .obsidian/plugins/linkedin-poster/ directory.
- Create a LinkedIn Company Page (required by LinkedIn for developer apps, even for personal use — it can be minimal)
- Go to LinkedIn Developer Portal and create a new app
- Associate the app with your Company Page
- Under Products, add both:
- Share on LinkedIn (grants
w_member_social— needed to create posts) - Sign In with LinkedIn using OpenID Connect (grants
openid,profile— needed to identify your account)
- Share on LinkedIn (grants
- Under Auth → OAuth 2.0 settings, add this redirect URI:
http://127.0.0.1:48734/callback - Verify on the Auth tab that all four scopes appear:
openid,profile,w_member_social,email
Important: Both products are required. "Share on LinkedIn" alone does not provide a way to identify your account, and the plugin will fail to connect without "Sign In with LinkedIn using OpenID Connect."
- In Obsidian, go to Settings → LinkedIn Poster
- Enter your Client ID and Client Secret from the LinkedIn Developer Portal
- Set your Drafts folder and Published folder (can be the same folder or separate — see Settings below)
- Click Connect LinkedIn Account — a browser window will open for you to authorize
- Once authorized, you'll see "Connected as [your name]" in settings
Troubleshooting auth: If you add the Sign In product after your first connection attempt, LinkedIn may cache the old consent. Go to LinkedIn → Settings → Data Privacy → Permitted Services, remove the app, then reconnect from the plugin.
The plugin discovers your identity automatically via OpenID Connect. If you ever need your numeric LinkedIn Member ID for debugging purposes, open your LinkedIn profile in a browser, open the developer console, and run:
fetch('/voyager/api/me',{headers:{'csrf-token':document.cookie.match(/JSESSIONID="?([^";]+)/)?.[1]}}).then(r=>r.text()).then(t=>prompt('ID',t.match(/li:member:(\d+)/)?.[1]||'none'))This will display your numeric member ID in a prompt dialog.
- Open the command palette (
Cmd/Ctrl + P) - Run "New LinkedIn Post"
- Enter a URL to share (or leave empty for a text-only post)
- A new note is created in your drafts folder with pre-filled frontmatter
- Write your commentary in the note body
- With your post note open, open the command palette
- Run "Post to LinkedIn"
- Review the preview (if enabled) — shows processed text, character count, and visibility
- Click "Post to LinkedIn" in the preview modal
- The note's frontmatter is updated with the post date and LinkedIn URL, and the note is moved to your published folder
Notes are created with this structure:
---
url: "https://example.com/article"
status: draft
tags: life/career/linkedin/posts
visibility: public
posted_date:
linkedin_url:
---
Your commentary here...After posting, the frontmatter is automatically updated:
---
url: "https://example.com/article"
status: posted
tags: life/career/linkedin/posts
visibility: public
posted_date: 2026-03-28T19:30:00.000Z
linkedin_url: https://www.linkedin.com/feed/update/urn:li:share:7012345678901234567
---| Setting | Default | Description |
|---|---|---|
| Client ID | — | LinkedIn app Client ID from the Developer Portal |
| Client Secret | — | LinkedIn app Client Secret from the Developer Portal |
| Drafts folder | — | Folder where new post notes are created |
| Published folder | — | Folder where posts are moved after publishing. Can be the same as drafts folder if you don't want separation. |
| Default tag | life/career/linkedin/posts |
Tag applied to new post notes in frontmatter |
| Default visibility | public |
public or connections — can be overridden per-post in frontmatter |
| Show preview before posting | On | Display a preview modal with the processed text before publishing |
| Command | Description |
|---|---|
| New LinkedIn Post | Create a new post note (prompts for optional URL) |
| Post to LinkedIn | Publish the active note to LinkedIn |
| Connect LinkedIn Account | Start the OAuth authorization flow |
LinkedIn supports limited formatting. The plugin automatically converts your Markdown:
| Markdown | Result | Notes |
|---|---|---|
**bold** |
bold | Kept as-is — LinkedIn supports this |
*italic* |
italic | Kept as-is |
- item / 1. item |
Lists | Kept as-is |
# Heading |
Heading | # prefix stripped, text kept |
[text](url) |
text (url) | Link syntax converted to plain text |
 |
(removed) | Images removed entirely |
`code` |
code | Backticks stripped |
| Code blocks | Plain text | Fences removed, content kept |
- Access tokens last 60 days and are refreshed automatically when within 7 days of expiry
- Refresh tokens last 365 days — if expired, you'll be prompted to reconnect
- All tokens are stored in Obsidian's SecretStorage — they never appear in your vault files or sync
- Obsidian v1.11.4 or later (for SecretStorage API)
- Desktop only (the OAuth flow uses a local HTTP server)
MIT