or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mdcontent-generation.mdcontent-management.mdcontent-reading.mdindex.mdmain-application.mdplugin-system.mdsettings-configuration.mdutilities.md

cli-tools.mddocs/

0

# Command-Line Tools

1

2

Specialized CLI utilities for site setup, content import, theme management, and plugin operations. These tools provide convenient interfaces for common Pelican workflow tasks.

3

4

## Capabilities

5

6

### pelican-quickstart

7

8

Interactive site setup tool that creates initial project structure, configuration files, and basic content templates.

9

10

```python { .api }

11

def main() -> None:

12

"""

13

Main entry point for pelican-quickstart command.

14

15

Provides interactive prompts for:

16

- Site title and author information

17

- URL structure and paths

18

- Timezone and language settings

19

- Theme selection

20

- Plugin preferences

21

- Makefile and automation setup

22

"""

23

```

24

25

**Command usage:**

26

```bash

27

pelican-quickstart

28

```

29

30

**Features:**

31

- Interactive setup wizard with sensible defaults

32

- Creates project directory structure

33

- Generates `pelicanconf.py` configuration file

34

- Creates `publishconf.py` for production settings

35

- Optional Makefile and Fabric scripts for automation

36

- Sample content creation

37

38

### pelican-import

39

40

Content import utility supporting multiple blog platforms and formats for migrating existing content to Pelican.

41

42

```python { .api }

43

def main() -> None:

44

"""

45

Main entry point for pelican-import command.

46

47

Supports importing from:

48

- WordPress XML exports

49

- Blogger XML exports

50

- Tumblr API

51

- Medium posts

52

- RSS/Atom feeds

53

- Dotclear exports

54

- Posterous backups

55

"""

56

```

57

58

**Command usage:**

59

```bash

60

# WordPress import

61

pelican-import --wordpress wordpress-export.xml -o content/

62

63

# Blogger import

64

pelican-import --blogger blogger-export.xml -o content/

65

66

# RSS feed import

67

pelican-import --feed https://example.com/feed.xml -o content/

68

69

# Tumblr import (requires API key)

70

pelican-import --tumblr myblog.tumblr.com -o content/

71

```

72

73

**Import Features:**

74

- Automatic metadata extraction and conversion

75

- Image and media file downloading

76

- Tag and category mapping

77

- Content format conversion (HTML to Markdown optional)

78

- Duplicate detection and handling

79

- Custom field preservation

80

81

### pelican-themes

82

83

Theme management utility for installing, removing, and listing Pelican themes.

84

85

```python { .api }

86

def main() -> None:

87

"""

88

Main entry point for pelican-themes command.

89

90

Operations:

91

- Install themes from local directories or Git repositories

92

- Remove installed themes

93

- List available and installed themes

94

- Symlink themes for development

95

- Theme validation and compatibility checking

96

"""

97

```

98

99

**Command usage:**

100

```bash

101

# Install theme from directory

102

pelican-themes --install path/to/theme/

103

104

# Install theme from Git repository

105

pelican-themes --install https://github.com/user/theme.git

106

107

# Install and symlink for development

108

pelican-themes --install --symlink path/to/theme/

109

110

# List installed themes

111

pelican-themes --list

112

113

# Remove theme

114

pelican-themes --remove theme-name

115

116

# Get theme information

117

pelican-themes --info theme-name

118

```

119

120

**Theme Operations:**

121

- Theme validation and dependency checking

122

- Automatic theme asset handling

123

- Theme metadata extraction

124

- Conflict resolution

125

- Development symlink support

126

127

### pelican-plugins

128

129

Plugin discovery and management utility for listing available plugins and their information.

130

131

```python { .api }

132

def list_plugins() -> None:

133

"""

134

Main entry point for pelican-plugins command.

135

136

Features:

137

- List all available plugins in plugin paths

138

- Show plugin metadata and descriptions

139

- Display plugin dependencies and requirements

140

- Plugin status and compatibility information

141

"""

142

```

143

144

**Command usage:**

145

```bash

146

# List all available plugins

147

pelican-plugins

148

149

# Show detailed plugin information

150

pelican-plugins --info

151

152

# List plugins in specific path

153

pelican-plugins --path custom/plugins/

154

```

155

156

## CLI Tool Configuration

157

158

### Import Tool Settings

159

160

Configure import behavior in settings or via command-line options:

161

162

```python

163

# Import-specific settings

164

IMPORT_WORDPRESS_POSTS_ONLY = False # Import pages as well as posts

165

IMPORT_CLEAN_HTML = True # Clean imported HTML

166

IMPORT_MARKDOWN_EXTENSION = '.md' # Extension for converted Markdown

167

IMPORT_PRESERVE_METADATA = True # Preserve custom metadata fields

168

```

169

170

### Theme Tool Settings

171

172

Configure theme installation and management:

173

174

```python

175

# Theme-specific settings

176

THEME_STATIC_DIR = 'theme' # Theme static files directory

177

THEME_STATIC_PATHS = ['static'] # Theme static source directories

178

THEME_TEMPLATES_OVERRIDES = [] # Template override directories

179

```

180

181

## Usage Examples

182

183

### Automated Site Setup

184

185

```bash

186

#!/bin/bash

187

# Automated Pelican site setup script

188

189

# Create project directory

190

mkdir my-blog

191

cd my-blog

192

193

# Run quickstart with predefined answers

194

echo -e "My Blog\nJohn Doe\nen\nAmerica/New_York\nhttps://myblog.com\ny\ny\nn\ny" | pelican-quickstart

195

196

# Install a theme

197

pelican-themes --install https://github.com/getpelican/pelican-themes.git

198

199

# Create first post

200

mkdir -p content

201

cat > content/first-post.md << EOF

202

Title: My First Post

203

Date: $(date +%Y-%m-%d)

204

Category: General

205

206

This is my first post using Pelican!

207

EOF

208

209

# Generate site

210

make html

211

```

212

213

### WordPress Migration Workflow

214

215

```bash

216

#!/bin/bash

217

# WordPress to Pelican migration script

218

219

# 1. Export WordPress content (done manually from WordPress admin)

220

# 2. Import content

221

pelican-import --wordpress wordpress-export.xml -o content/ --dir-cat

222

223

# 3. Convert HTML to Markdown (optional)

224

find content/ -name "*.html" -exec pandoc {} -f html -t markdown -o {}.md \;

225

find content/ -name "*.html" -delete

226

find content/ -name "*.md" -exec rename 's/\.html\.md$/.md/' {} \;

227

228

# 4. Download and organize images

229

python << EOF

230

import os

231

import re

232

import requests

233

from pathlib import Path

234

235

# Process all content files

236

for md_file in Path('content').glob('**/*.md'):

237

content = md_file.read_text()

238

239

# Find image URLs

240

img_urls = re.findall(r'!\[.*?\]\((https?://[^)]+)\)', content)

241

242

for url in img_urls:

243

# Download image

244

img_name = os.path.basename(url.split('?')[0])

245

img_path = Path('content/images') / img_name

246

img_path.parent.mkdir(exist_ok=True)

247

248

response = requests.get(url)

249

img_path.write_bytes(response.content)

250

251

# Update content with local path

252

content = content.replace(url, f'/images/{img_name}')

253

254

md_file.write_text(content)

255

EOF

256

257

# 5. Generate site

258

pelican content

259

```

260

261

### Theme Development Workflow

262

263

```bash

264

#!/bin/bash

265

# Theme development and testing workflow

266

267

# Create theme directory

268

mkdir -p themes/my-theme/templates

269

mkdir -p themes/my-theme/static/css

270

271

# Create basic theme files

272

cat > themes/my-theme/templates/base.html << EOF

273

<!DOCTYPE html>

274

<html>

275

<head>

276

<title>{{ SITENAME }}</title>

277

<link rel="stylesheet" href="{{ SITEURL }}/{{ THEME_STATIC_URL }}/css/style.css">

278

</head>

279

<body>

280

{% block content %}{% endblock %}

281

</body>

282

</html>

283

EOF

284

285

# Install theme for development (symlinked)

286

pelican-themes --install --symlink themes/my-theme/

287

288

# Test theme with sample content

289

pelican content -t my-theme -o output-test/

290

291

# Serve for testing

292

cd output-test

293

python -m http.server 8000

294

```

295

296

### Plugin Management Script

297

298

```python

299

#!/usr/bin/env python3

300

"""Plugin management helper script."""

301

302

import subprocess

303

import sys

304

from pathlib import Path

305

306

def list_available_plugins():

307

"""List all available plugins."""

308

result = subprocess.run(['pelican-plugins'], capture_output=True, text=True)

309

return result.stdout.split('\n')

310

311

def install_recommended_plugins():

312

"""Install commonly used plugins."""

313

recommended = [

314

'https://github.com/getpelican/pelican-plugins.git',

315

]

316

317

plugins_dir = Path('plugins')

318

plugins_dir.mkdir(exist_ok=True)

319

320

for plugin_repo in recommended:

321

plugin_name = plugin_repo.split('/')[-1].replace('.git', '')

322

plugin_path = plugins_dir / plugin_name

323

324

if not plugin_path.exists():

325

subprocess.run(['git', 'clone', plugin_repo, str(plugin_path)])

326

print(f"Installed plugin: {plugin_name}")

327

else:

328

print(f"Plugin already exists: {plugin_name}")

329

330

def update_plugins():

331

"""Update all git-based plugins."""

332

plugins_dir = Path('plugins')

333

334

for plugin_path in plugins_dir.iterdir():

335

if plugin_path.is_dir() and (plugin_path / '.git').exists():

336

print(f"Updating {plugin_path.name}...")

337

subprocess.run(['git', 'pull'], cwd=plugin_path)

338

339

if __name__ == '__main__':

340

if len(sys.argv) < 2:

341

print("Usage: plugin-manager.py [list|install|update]")

342

sys.exit(1)

343

344

command = sys.argv[1]

345

346

if command == 'list':

347

plugins = list_available_plugins()

348

for plugin in plugins:

349

if plugin.strip():

350

print(plugin)

351

elif command == 'install':

352

install_recommended_plugins()

353

elif command == 'update':

354

update_plugins()

355

else:

356

print(f"Unknown command: {command}")

357

sys.exit(1)

358

```

359

360

### Content Import Automation

361

362

```python

363

#!/usr/bin/env python3

364

"""Automated content import with processing."""

365

366

import subprocess

367

import sys

368

import re

369

from pathlib import Path

370

from datetime import datetime

371

372

def import_content(source_type, source_path, output_dir='content'):

373

"""Import content using pelican-import."""

374

cmd = ['pelican-import', f'--{source_type}', source_path, '-o', output_dir]

375

376

if source_type == 'wordpress':

377

cmd.extend(['--dir-cat', '--strip-raw'])

378

379

result = subprocess.run(cmd, capture_output=True, text=True)

380

381

if result.returncode == 0:

382

print(f"Successfully imported {source_type} content")

383

return True

384

else:

385

print(f"Import failed: {result.stderr}")

386

return False

387

388

def post_process_content(content_dir='content'):

389

"""Post-process imported content."""

390

content_path = Path(content_dir)

391

392

for md_file in content_path.glob('**/*.md'):

393

content = md_file.read_text()

394

modified = False

395

396

# Fix common import issues

397

# 1. Clean up WordPress shortcodes

398

content = re.sub(r'\[caption[^\]]*\](.*?)\[/caption\]', r'\1', content, flags=re.DOTALL)

399

content = re.sub(r'\[gallery[^\]]*\]', '', content)

400

401

# 2. Fix image references

402

content = re.sub(r'!\[\]\(([^)]+)\)', r'![](\1)', content)

403

404

# 3. Clean up extra whitespace

405

content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)

406

407

# 4. Ensure proper metadata formatting

408

lines = content.split('\n')

409

if lines and not lines[0].startswith(('Title:', 'Date:')):

410

# Add basic metadata if missing

411

title = md_file.stem.replace('-', ' ').title()

412

date = datetime.now().strftime('%Y-%m-%d')

413

metadata = f"Title: {title}\nDate: {date}\n\n"

414

content = metadata + content

415

modified = True

416

417

if modified:

418

md_file.write_text(content)

419

print(f"Post-processed: {md_file}")

420

421

if __name__ == '__main__':

422

if len(sys.argv) < 3:

423

print("Usage: import-content.py <source_type> <source_path>")

424

print("Example: import-content.py wordpress export.xml")

425

sys.exit(1)

426

427

source_type = sys.argv[1]

428

source_path = sys.argv[2]

429

430

# Import content

431

success = import_content(source_type, source_path)

432

433

if success:

434

# Post-process content

435

post_process_content()

436

print("Content import and processing complete!")

437

else:

438

print("Content import failed!")

439

sys.exit(1)

440

```