pagecord-cli 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e6a9d37234707507835ff1e87b324bccfacc7d680515b9674f0f0fa454cd704
4
- data.tar.gz: d0628c7e0c4e1273cb24a870f9db83e9ec25da7f01395eae3503f4aa1900f130
3
+ metadata.gz: cf505ffa08cc845661d677e1b4e5175ed12151719a68bf6e36e74899aca6c735
4
+ data.tar.gz: 11c57b10cf54268f70bec8eab14c4daf2ffb3abc3b10183cbe90e6e3a9bb15a5
5
5
  SHA512:
6
- metadata.gz: 300fd7fe1c31e8ab0196b8a8c0d8509819ec2d0882ea3bbbc98a4c34d4aaac22d05325a4197b4fcd5f1ff79480566c7d764acbd1ee173926e31c004f4b91b510
7
- data.tar.gz: d016d8f89cf2150b0a25872543603e19fdf87322ec5a9206c3aa532bf50de98f916df3a83de59c9815d530287ffcddae9236b9f4195ee8ad0c3fb3839b2dede6
6
+ metadata.gz: 2d6eabb97a9acb6ee7c3f61f7ccc676d7db740b7b2516583218a0902ca8fc5b4950eeb4143b1315e9adce799193f48c72bcfa9d3e625c91130bee6c3df814186
7
+ data.tar.gz: 194d199f07c81ef3f6d385179e79222a5dac4b0984a2a470ff5f5ac52f0097992b013f264e443fec601ad1dc37e62ff9566a2bb68bccd82d15a2defc11a5f820
data/README.md CHANGED
@@ -79,6 +79,19 @@ and HTML otherwise. Other flags: `--title`, `--status draft|published`,
79
79
  `--slug`, `--published-at`, `--tags`, `--canonical-url`, `--locale` and
80
80
  `--hidden`/`--no-hidden`. `--json` prints the full response.
81
81
 
82
+ ## Agent skill
83
+
84
+ The gem includes a skill that teaches coding agents such as Claude Code to use
85
+ the CLI:
86
+
87
+ ```bash
88
+ pagecord skill # print it
89
+ pagecord skill install # install it for your agents
90
+ ```
91
+
92
+ `install` writes it to `~/.agents/skills/pagecord` and links it into
93
+ `~/.claude/skills`. Run it again after upgrading the gem.
94
+
82
95
  ## Choosing a blog
83
96
 
84
97
  With one blog configured, every command uses it. With several, set a default
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: pagecord
3
+ description: Manage a Pagecord blog with the `pagecord` CLI. Use when the user wants to list, read, write or edit posts, pages or drafts, publish a local Markdown or HTML file, restyle their blog (theme, font, layout, colours, custom CSS), or add custom head or footer code.
4
+ allowed-tools: Bash, Read, Write, Edit, WebFetch
5
+ ---
6
+
7
+ # Pagecord
8
+
9
+ Everything here runs through the `pagecord` command. `pagecord --help` lists
10
+ every command and flag; `pagecord version` says which version is installed.
11
+
12
+ ## Rules
13
+
14
+ 1. **Draft unless told to publish.** Pass `--status draft` to `post create` and
15
+ `post update`, and use `pagecord draft FILE` rather than `publish`, unless
16
+ the user asked to publish.
17
+ 2. **Posts and pages are addressed by token**, eight hex characters such as
18
+ `aaa33a9b`. `post list` shows them.
19
+ 3. **Content is HTML.** `post show` returns HTML; edit it as HTML and send it
20
+ back with `--content-file`. A file ending `.md` is sent as Markdown.
21
+ 4. **`custom-code update` replaces the whole field.** Save the current value
22
+ first and keep it as the backup.
23
+ 5. **Never create an API key.** If `pagecord blog list` prints nothing, ask the
24
+ user to run `pagecord login SUBDOMAIN` with a key from Settings > API.
25
+ 6. **Pass `--json` when you need to parse output.**
26
+
27
+ ## Quick reference
28
+
29
+ | To | Run |
30
+ |----|-----|
31
+ | List posts | `pagecord post list [--drafts\|--published] [--page N]` |
32
+ | Read a post | `pagecord post show TOKEN` |
33
+ | Edit a post | `pagecord post update TOKEN --content-file F [--title T] [--status draft]` |
34
+ | Write a post | `pagecord post create --title T --content-file F --status draft` |
35
+ | Delete a post | `pagecord post delete TOKEN [--permanent]` |
36
+ | Pages | `pagecord page list\|show\|create\|update\|delete`, as for posts |
37
+ | Publish a file | `pagecord publish FILE` or `pagecord draft FILE` |
38
+ | Theme and fonts | `pagecord appearance show\|update` |
39
+ | Custom CSS, head, footer | `pagecord custom-code show\|update` |
40
+ | Blogs | `pagecord blog list`, `pagecord blog use SUBDOMAIN` |
41
+
42
+ With several blogs configured, pass `--blog SUBDOMAIN` or set a default with
43
+ `pagecord blog use`. Lists return 15 at a time, newest first; `--page 2` gets
44
+ the next 15. The home page isn't covered by the CLI yet.
45
+
46
+ ## Editing posts
47
+
48
+ ```bash
49
+ pagecord post show TOKEN --json # fields plus the HTML content
50
+ pagecord post update TOKEN --content-file post.html --status draft
51
+ ```
52
+
53
+ `update` changes only the flags given. Other fields: `--slug`,
54
+ `--published-at`, `--tags "a, b"`, `--canonical-url`, `--locale`,
55
+ `--hidden`/`--no-hidden`. Delete moves a post to the bin unless you pass
56
+ `--permanent`, which can't be undone: confirm with the user first.
57
+
58
+ ## Publishing files
59
+
60
+ ```bash
61
+ pagecord publish hello.md # publish or update
62
+ pagecord draft notes/idea.md # save as a draft
63
+ ```
64
+
65
+ The first run writes a `pagecord_token` into the file's front matter, and later
66
+ runs update that same post. Front matter can set `title`, `slug`, `tags`,
67
+ `published_at`, `canonical_url`, `hidden` and `locale`. Local images written as
68
+ `![alt](photo.jpg)` are uploaded.
69
+
70
+ ## Restyling a blog
71
+
72
+ Read https://help.pagecord.com/custom-css before the first CSS change. It
73
+ documents every class you can target and what Pagecord accepts. Don't work out
74
+ the structure by scraping a blog: comments load on demand and are missing from
75
+ the page source.
76
+
77
+ Look at the theme first, since your CSS has to work with it:
78
+
79
+ ```bash
80
+ pagecord appearance show
81
+ pagecord custom-code show --css > blog.css
82
+ cp blog.css blog.css.orig
83
+ ```
84
+
85
+ Edit `blog.css`, show the user a diff, then save it:
86
+
87
+ ```bash
88
+ pagecord custom-code update --css blog.css
89
+ ```
90
+
91
+ Undoing is `pagecord custom-code update --css blog.css.orig`; tell the user.
92
+
93
+ Pagecord rejects CSS that is over 16KB, nested (`.post { .title { } }`), or
94
+ `@import`s anything but HTTPS Google Fonts or Bunny Fonts. A rejected update
95
+ changes nothing. Custom properties, `@supports` and `@layer` are fine.
96
+
97
+ Prefer overriding the theme's custom properties, which work in light and dark
98
+ mode, over restyling elements one by one:
99
+
100
+ ```css
101
+ :root {
102
+ --theme-bg: #faf7f0;
103
+ --theme-text: #2b2b2b;
104
+ --theme-accent: #8c5a3c;
105
+ --font-body: Georgia, serif;
106
+ --font-size-base: 112.5%;
107
+ }
108
+ ```
109
+
110
+ Scope rules with the attributes on `<body>`: `data-page-type` is `index`,
111
+ `home-page`, `page` or `post`, and `data-slug` is the slug being viewed. Target
112
+ `.post-body`, never classes containing `lexxy`, which may be renamed.
113
+
114
+ Whole-theme changes belong in `appearance update`, not CSS:
115
+ `--theme`, `--font`, `--width`, `--layout`, the six `--custom-theme-*` colours
116
+ and `--show-branding true|false`. The Theme Garden in Settings > Appearance
117
+ applies curated designs in one click.
118
+
119
+ `--footer-html`, `--head-html` and `--body-html` work like `--css` and each
120
+ take a file path. `--enabled false` switches head and body code off without
121
+ deleting it.
122
+
123
+ ## Always verify
124
+
125
+ After any change, load the blog and check it. A successful update only means
126
+ the change was saved.
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "io/console"
4
4
  require "json"
5
+ require "fileutils"
5
6
  require "optparse"
6
7
 
7
8
  module PagecordCLI
@@ -21,6 +22,8 @@ module PagecordCLI
21
22
  "body-html" => "custom_body_html"
22
23
  }.freeze
23
24
 
25
+ SKILL_PATH = File.expand_path("SKILL.md", __dir__)
26
+
24
27
  attr_reader :argv, :config, :input, :output, :error, :options
25
28
 
26
29
  def initialize(argv, config: Config.new, input: $stdin, output: $stdout, error: $stderr)
@@ -34,6 +37,7 @@ module PagecordCLI
34
37
 
35
38
  def run
36
39
  return help if argv.empty? || %w[help -h --help].include?(argv.first)
40
+ return version if %w[version -v --version].include?(argv.first)
37
41
 
38
42
  parser.order!(argv)
39
43
  command = argv.shift
@@ -47,6 +51,7 @@ module PagecordCLI
47
51
  when "custom-code" then custom_code
48
52
  when "post" then records("posts")
49
53
  when "page" then records("pages")
54
+ when "skill" then skill
50
55
  when "publish" then publish("published")
51
56
  when "draft" then publish("draft")
52
57
  else
@@ -308,6 +313,34 @@ module PagecordCLI
308
313
  params
309
314
  end
310
315
 
316
+ def skill
317
+ case argv.shift
318
+ when nil then output.print File.read(SKILL_PATH)
319
+ when "install" then install_skill
320
+ else return fail_with("Usage: pagecord skill [install]")
321
+ end
322
+ 0
323
+ end
324
+
325
+ def install_skill
326
+ dir = File.join(Dir.home, ".agents", "skills", "pagecord")
327
+ FileUtils.mkdir_p(dir)
328
+ FileUtils.cp(SKILL_PATH, dir)
329
+ File.write(File.join(dir, ".installed-version"), VERSION)
330
+ say "Installed the Pagecord skill to #{dir}"
331
+
332
+ link = File.join(Dir.home, ".claude", "skills", "pagecord")
333
+ return if File.symlink?(link) && File.readlink(link) == dir
334
+
335
+ if File.exist?(link) || File.symlink?(link)
336
+ error.puts "#{link} already exists, so Claude Code will keep using that. Remove it and run this again to use this skill."
337
+ else
338
+ FileUtils.mkdir_p(File.dirname(link))
339
+ File.symlink(dir, link)
340
+ say "Linked it into #{link}"
341
+ end
342
+ end
343
+
311
344
  def publish(status)
312
345
  overrides = {}
313
346
  parser do |opts|
@@ -316,7 +349,7 @@ module PagecordCLI
316
349
  opts.on("--published-at TIME") { |value| overrides[:published_at] = value }
317
350
  opts.on("--tags TAGS") { |value| overrides[:tags] = value }
318
351
  opts.on("--canonical-url URL") { |value| overrides[:canonical_url] = value }
319
- opts.on("--hidden") { overrides[:hidden] = true }
352
+ opts.on("--[no-]hidden") { |value| overrides[:hidden] = value }
320
353
  opts.on("--locale LOCALE") { |value| overrides[:locale] = value }
321
354
  end.parse!(argv)
322
355
 
@@ -412,9 +445,17 @@ module PagecordCLI
412
445
  end
413
446
  end
414
447
 
448
+ def version
449
+ options[:json] = argv.include?("--json")
450
+ options[:json] ? print_json({ version: VERSION }) : output.puts("pagecord #{VERSION}")
451
+ 0
452
+ end
453
+
415
454
  def help
416
455
  output.puts <<~HELP
417
456
  Usage:
457
+ pagecord version
458
+ pagecord skill [install]
418
459
  pagecord login SUBDOMAIN
419
460
  pagecord logout [SUBDOMAIN]
420
461
  pagecord blog list
@@ -437,21 +478,16 @@ module PagecordCLI
437
478
  --json machine-readable output
438
479
  --quiet suppress confirmation messages
439
480
 
440
- Publish options:
481
+ Post options (publish, draft, post and page):
441
482
  --title TITLE
442
483
  --slug SLUG
443
484
  --published-at TIME
444
485
  --tags TAGS
445
486
  --canonical-url URL
446
- --hidden
447
487
  --locale LOCALE
448
-
449
- Post and page options:
450
- --title TITLE
451
- --content-file PATH (HTML, or Markdown if it ends .md)
452
- --status draft|published
453
- --slug, --published-at, --tags, --canonical-url, --locale
454
488
  --hidden, --no-hidden
489
+ --content-file PATH post/page create and update; Markdown if it ends .md
490
+ --status draft|published post/page create and update
455
491
 
456
492
  Appearance options:
457
493
  --theme, --font, --width, --layout
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PagecordCLI
4
- VERSION = "0.3.0"
4
+ VERSION = "0.3.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pagecord-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Olly Headey
@@ -20,6 +20,7 @@ files:
20
20
  - README.md
21
21
  - bin/pagecord
22
22
  - lib/pagecord_cli.rb
23
+ - lib/pagecord_cli/SKILL.md
23
24
  - lib/pagecord_cli/cli.rb
24
25
  - lib/pagecord_cli/client.rb
25
26
  - lib/pagecord_cli/config.rb
@@ -46,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
48
49
  requirements: []
49
- rubygems_version: 4.0.16
50
+ rubygems_version: 4.0.20
50
51
  specification_version: 4
51
52
  summary: Publish local files to Pagecord
52
53
  test_files: []