···0000000000000000000000000000000000000000000000000000000001## [0.2.0] - 2026-02-01
23### ๐ Features
···78### โ๏ธ Miscellaneous Tasks
9000010- Update blog post
11- Fix blog build error
12- Adjust blog post
···1+## [0.3.3.] - 2026-02-04
2+3+### โ๏ธ Miscellaneous Tasks
4+5+- Cleaned up remaining auth implementations
6+- Format
7+8+## [0.3.2] - 2026-02-05
9+10+### ๐ Bug Fixes
11+12+- Fixed issue with auth selection in init command
13+14+### โ๏ธ Miscellaneous Tasks
15+16+- Release 0.3.2
17+## [0.3.1] - 2026-02-04
18+19+### ๐ Bug Fixes
20+21+- Asset subdirectories
22+23+### โ๏ธ Miscellaneous Tasks
24+25+- Updated authentication ux
26+- Release 0.3.1
27+- Bumped version
28+## [0.3.0] - 2026-02-04
29+30+### ๐ Features
31+32+- Initial oauth implementation
33+- Add stripDatePrefix option for Jekyll-style filenames
34+- Add `update` command
35+36+### โ๏ธ Miscellaneous Tasks
37+38+- Update changelog
39+- Added workflows
40+- Updated workflows
41+- Updated workflows
42+- Cleaned up types
43+- Updated icon styles
44+- Updated og image
45+- Updated docs
46+- Docs updates
47+- Bumped version
48+## [0.2.1] - 2026-02-02
49+50+### โ๏ธ Miscellaneous Tasks
51+52+- Added CHANGELOG
53+- Merge main into chore/fronmatter-config-updates
54+- Added linting and formatting
55+- Linting updates
56+- Refactored to use fallback approach if frontmatter.slugField is provided or not
57+- Version bump
58## [0.2.0] - 2026-02-01
5960### ๐ Features
···6465### โ๏ธ Miscellaneous Tasks
6667+- Resolved action items from issue #3
68+- Adjusted tags to accept yaml multiline arrays for tags
69+- Updated inject to handle new slug options
70+- Updated comments
71- Update blog post
72- Fix blog build error
73- Adjust blog post
···1+# CLAUDE.md
2+3+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+5+## Project Overview
6+7+Sequoia is a CLI tool for publishing Markdown documents with frontmatter to the AT Protocol (Bluesky's decentralized social network). It converts blog posts into ATProto records (`site.standard.document`, `space.litenote.note`) and publishes them to a user's PDS.
8+9+Website: <https://sequoia.pub>
10+11+## Monorepo Structure
12+13+- **`packages/cli/`** โ Main CLI package (the core product)
14+- **`docs/`** โ Documentation website (Vocs-based, deployed to Cloudflare Pages)
15+16+Bun workspaces manage the monorepo.
17+18+## Commands
19+20+```bash
21+# Build CLI
22+bun run build:cli
23+24+# Run CLI in dev (build + link)
25+cd packages/cli && bun run dev
26+27+# Run tests
28+bun run test:cli
29+30+# Run a single test file
31+cd packages/cli && bun test src/lib/markdown.test.ts
32+33+# Lint (auto-fix)
34+cd packages/cli && bun run lint
35+36+# Format (auto-fix)
37+cd packages/cli && bun run format
38+39+# Docs dev server
40+bun run dev:docs
41+```
42+43+## Architecture
44+45+**Entry point:** `packages/cli/src/index.ts` โ Uses `cmd-ts` for type-safe subcommand routing.
46+47+**Commands** (`src/commands/`):
48+49+- `publish` โ Core workflow: scans markdown files, publishes to ATProto
50+- `sync` โ Fetches published records state from ATProto
51+- `update` โ Updates existing records
52+- `auth` โ Multi-identity management (app-password + OAuth)
53+- `init` โ Interactive config setup
54+- `inject` โ Injects verification links into static HTML output
55+- `login` โ Legacy auth (deprecated)
56+57+**Libraries** (`src/lib/`):
58+59+- `atproto.ts` โ ATProto API wrapper (two client types: AtpAgent for app-password, OAuth client)
60+- `config.ts` โ Loads `sequoia.json` config and `.sequoia-state.json` state files
61+- `credentials.ts` โ Multi-identity credential storage at `~/.config/sequoia/credentials.json` (0o600 permissions)
62+- `markdown.ts` โ Frontmatter parsing (YAML/TOML), content hashing, atUri injection
63+64+**Extensions** (`src/extensions/`):
65+66+- `litenote.ts` โ Creates `space.litenote.note` records with embedded images
67+68+## Key Patterns
69+70+- **Config resolution:** `sequoia.json` is found by searching up the directory tree
71+- **Frontmatter formats:** YAML (`---`), TOML (`+++`), and alternative (`***`) delimiters
72+- **Credential types:** App-password (PDS URL + identifier + password) and OAuth (DID + handle)
73+- **Build:** `bun build src/index.ts --target node --outdir dist`
74+75+## Tooling
76+77+- **Runtime/bundler:** Bun
78+- **Linter/formatter:** Biome (tabs, double quotes)
79+- **Test runner:** Bun's native test runner
80+- **CLI framework:** `cmd-ts`
81+- **Interactive UI:** `@clack/prompts`
82+83+## Git Conventions
84+85+Never add 'Co-authored-by' lines to git commits unless explicitly asked.
···1# CLI Reference
200000000000000003## `auth`
45```bash [Terminal]
6sequoia auth
7-> Authenticate with your ATProto PDS
89OPTIONS:
10 --logout <str> - Remove credentials for a specific identity (or all if only one exists) [optional]
···13 --list - List all stored identities [optional]
14 --help, -h - show help [optional]
15```
001617## `init`
18···61 --dry-run, -n - Preview what would be synced without making changes [optional]
62 --help, -h - show help [optional]
63```
000000000000000
···1# CLI Reference
23+## `login`
4+5+```bash [Terminal]
6+sequoia login
7+> Login with OAuth (browser-based authentication)
8+9+OPTIONS:
10+ --logout <str> - Remove OAuth session for a specific DID [optional]
11+12+FLAGS:
13+ --list - List all stored OAuth sessions [optional]
14+ --help, -h - show help [optional]
15+```
16+17+OAuth is the recommended authentication method as it scopes permissions and refreshes tokens automatically.
18+19## `auth`
2021```bash [Terminal]
22sequoia auth
23+> Authenticate with your ATProto PDS using an app password
2425OPTIONS:
26 --logout <str> - Remove credentials for a specific identity (or all if only one exists) [optional]
···29 --list - List all stored identities [optional]
30 --help, -h - show help [optional]
31```
32+33+Use this as an alternative to `login` when OAuth isn't available or for CI environments.
3435## `init`
36···79 --dry-run, -n - Preview what would be synced without making changes [optional]
80 --help, -h - show help [optional]
81```
82+83+## `update`
84+85+```bash [Terminal]
86+sequoia update
87+> Update local config or ATProto publication record
88+89+FLAGS:
90+ --help, -h - show help [optional]
91+```
92+93+Interactive command to modify your existing configuration. Choose between:
94+95+- **Local configuration**: Edit `sequoia.json` settings including site URL, directory paths, frontmatter mappings, advanced options, and Bluesky settings
96+- **ATProto publication**: Update your publication record's name, description, URL, icon, and discover visibility
+13
docs/docs/pages/config.mdx
···17| `frontmatter.slugField` | `string` | No | - | Frontmatter field to use for slug (defaults to filepath) |
18| `ignore` | `string[]` | No | - | Glob patterns for files to ignore |
19| `removeIndexFromSlug` | `boolean` | No | `false` | Remove `/index` or `/_index` suffix from slugs |
020| `bluesky` | `object` | No | - | Bluesky posting configuration |
21| `bluesky.enabled` | `boolean` | No | `false` | Post to Bluesky when publishing documents |
22| `bluesky.maxAgeDays` | `number` | No | `30` | Only post documents published within this many days |
···95```
9697If the frontmatter field is not found, it falls back to the filepath.
0000000000009899### Ignoring Files
100
···17| `frontmatter.slugField` | `string` | No | - | Frontmatter field to use for slug (defaults to filepath) |
18| `ignore` | `string[]` | No | - | Glob patterns for files to ignore |
19| `removeIndexFromSlug` | `boolean` | No | `false` | Remove `/index` or `/_index` suffix from slugs |
20+| `stripDatePrefix` | `boolean` | No | `false` | Remove `YYYY-MM-DD-` date prefixes from slugs (Jekyll-style) |
21| `bluesky` | `object` | No | - | Bluesky posting configuration |
22| `bluesky.enabled` | `boolean` | No | `false` | Post to Bluesky when publishing documents |
23| `bluesky.maxAgeDays` | `number` | No | `30` | Only post documents published within this many days |
···96```
9798If the frontmatter field is not found, it falls back to the filepath.
99+100+### Jekyll-Style Date Prefixes
101+102+Jekyll uses date prefixes in filenames (e.g., `2024-01-15-my-post.md`) for ordering posts. To strip these from generated slugs:
103+104+```json
105+{
106+ "stripDatePrefix": true
107+}
108+```
109+110+This transforms `2024-01-15-my-post.md` into the slug `my-post`.
111112### Ignoring Files
113
+9-7
docs/docs/pages/quickstart.mdx
···31sequoia
32```
3334-### Authorize
35-36-In order for Sequoia to publish or update records on your PDS, you need to authorize it with your ATProto handle and an app password.
3738-:::tip
39-You can create an app password [here](https://bsky.app/settings/app-passwords)
40-:::
4142```bash [Terminal]
43-sequoia auth
44```
0000004546### Initialize
47
···31sequoia
32```
3334+### Login
003536+In order for Sequoia to publish or update records on your PDS, you need to authenticate with your ATProto account.
003738```bash [Terminal]
39+sequoia login
40```
41+42+This will open your browser to complete OAuth authentication, and your sessions will refresh automatically as you use the CLI.
43+44+:::tip
45+Alternatively, you can use `sequoia auth` to authenticate with an [app password](https://bsky.app/settings/app-passwords) instead of OAuth.
46+:::
4748### Initialize
49
docs/docs/public/icon-dark.png
This is a binary file and will not be displayed.
docs/docs/public/og.png
This is a binary file and will not be displayed.
+2-1
package.json
···11 "build:docs": "cd docs && bun run build",
12 "build:cli": "cd packages/cli && bun run build",
13 "deploy:docs": "cd docs && bun run deploy",
14- "deploy:cli": "cd packages/cli && bun run deploy"
015 },
16 "devDependencies": {
17 "@types/bun": "latest",
···11 "build:docs": "cd docs && bun run build",
12 "build:cli": "cd packages/cli && bun run build",
13 "deploy:docs": "cd docs && bun run deploy",
14+ "deploy:cli": "cd packages/cli && bun run deploy",
15+ "test:cli": "cd packages/cli && bun test"
16 },
17 "devDependencies": {
18 "@types/bun": "latest",