Skip to content

Add GitHub CLI login flow#26

Merged
abechan1 merged 8 commits into
mainfrom
revert-25-revert-23-codex/implement-github-authentication-for-cli
Jun 28, 2026
Merged

Add GitHub CLI login flow#26
abechan1 merged 8 commits into
mainfrom
revert-25-revert-23-codex/implement-github-authentication-for-cli

Conversation

@abechan1

@abechan1 abechan1 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Reverts #25

Summary by CodeRabbit

  • 新機能
    • slidict auth を追加しました(GitHub デバイスコード方式で認証し、CLI用アクセストークンを保存)。
    • slidict slides を追加しました(list/show/create/edit に加え、--publish で下書き反映、--slide-id で下書き編集)。
  • 改善
    • ヘルプ/案内を拡充し、主要オプション(--publish--slide-id--slide-title--visibility)の説明を追加しました。
  • テスト
    • 認証・トークン保存(内容/パーミッション)・スライド操作の成功/失敗を検証しました。

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0b980303-dbee-4b98-8c5b-51b7d199f4d0

📥 Commits

Reviewing files that changed from the base of the PR and between c22589b and 09691b6.

📒 Files selected for processing (4)
  • lib/slidict/cli.rb
  • lib/slidict/slides_command.rb
  • lib/slidict/version.rb
  • spec/slidict/slides_command_spec.rb
✅ Files skipped from review due to trivial changes (1)
  • lib/slidict/version.rb
🚧 Files skipped from review as they are similar to previous changes (3)
  • spec/slidict/slides_command_spec.rb
  • lib/slidict/slides_command.rb
  • lib/slidict/cli.rb

📝 Walkthrough

Walkthrough

GitHub デバイスコード認証、CLI トークン保存、slidict slides の公開・編集オプション、slides API 呼び出し、関連テスト、コマンド案内が追加されました。

Changes

CLI 認証とスライド管理

Layer / File(s) Summary
Wiring と公開読み込み
AGENTS.md, lib/slidict.rb, lib/slidict/version.rb
新しい認証・スライド管理クラスの require が追加され、開発手順に README 更新指針が追記され、バージョンが更新された。
Auth と認証保存
lib/slidict/auth_client.rb, lib/slidict/credentials.rb, lib/slidict/cli.rb, spec/slidict/cli_spec.rb, spec/slidict/credentials_spec.rb, README.md
Slidict::AuthClientSlidict::Credentials が追加され、CLIauth 分岐、認証保存、認証ヘルプ、関連テスト、README の認証案内が追加された。
Slides API とコマンド
lib/slidict/slides_client.rb, lib/slidict/slides_command.rb, lib/slidict/cli.rb, spec/slidict/slides_client_spec.rb, spec/slidict/slides_command_spec.rb, spec/slidict/cli_spec.rb, README.md
Slidict::SlidesClientSlidict::SlidesCommand が追加され、CLIslides 分岐、公開・編集オプション、一覧/詳細/作成/更新、エラー処理、関連テストが追加された。

Review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • slidict/slidict-cli#23: Slidict::AuthClient / Slidict::CredentialsCLI#auth のデバイスコード認証導線が重なっています。

Suggested labels

codex

Poem

ぴょこんと耳を立てて auth
ちょこんとトークンをしまって、
slides でスライドを並べれば、
月夜のうさぎもにっこり。
ぴかぴかのコマンド、できあがり 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed GitHub の CLI ログインフロー追加を端的に表しており、変更内容の主題と一致しています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch revert-25-revert-23-codex/implement-github-authentication-for-cli

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@abechan1 abechan1 force-pushed the revert-25-revert-23-codex/implement-github-authentication-for-cli branch from 19ae87d to ab94927 Compare June 27, 2026 01:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
spec/slidict/cli_spec.rb (1)

92-103: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Pending 後の待機もこのテストで固定しておきたいです。

このケースは 1 回 Pending を返しているのに sleeper.sleep(1) を検証していないので、待機処理が消えてもテストが通ります。ポーリング退行を拾えるようにここも期待値に入れておくと安心です。

修正例
-      sleeper = double("sleeper", sleep: nil)
+      sleeper = double("sleeper")
@@
+      expect(sleeper).to receive(:sleep).with(1).once
       status = cli.run(["auth"])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spec/slidict/cli_spec.rb` around lines 92 - 103, The auth flow test around
described_class.new and cli.run(["auth"]) is missing an assertion for the
Pending backoff, so it would still pass if the polling sleep were removed.
Update this spec to expect the injected sleeper double to receive sleep(1)
during the pending-to-success path, alongside the existing token write
expectation, so the polling behavior in cli.run and the auth client handling
remains covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/slidict/auth_client.rb`:
- Around line 39-40: `AuthClient` では `authorization_pending` と `slow_down` を同じ
`Pending` にまとめないよう修正してください。`AuthClient#...` の `response["error"]` 判定で
`slow_down` は別例外(または別の戻り値)に分け、`CLI#auth` 側でそれを rescue
して次回の待機時間を増やすバックオフ処理を入れてください。`authorization_pending` は従来どおり `Pending`
のままにし、`slow_down` だけポーリング間隔を伸ばせるようにしてください。
- Line 25: `AuthClient` の `verification_uri` フォールバックが文字列連結になっており、`base_url`
の末尾スラッシュやサブパスで不正な URL になる可能性があります。`AuthClient#initialize` 内の `verification_uri`
生成を、同クラスの `post_json` と同じ URL 解決方針に合わせて `URI.join`
ベースに置き換え、`SLIDICT_AUTH_BASE_URL` の値に依存せず安全に `cli/activate` を組み立てるよう修正してください。

In `@lib/slidict/cli.rb`:
- Around line 145-160: The `slidict auth` flow only rescues `AuthClient::Error`
and `KeyError`, so failures from `credentials.write_cli_token!` can still crash
with `SystemCallError`. Update the `Slidict::CLI` auth path to catch save-time
OS errors around `credentials.write_cli_token!`, convert them into a user-facing
`@output.puts "Error: ..."` message, and return `1` just like the existing auth
failures.

---

Nitpick comments:
In `@spec/slidict/cli_spec.rb`:
- Around line 92-103: The auth flow test around described_class.new and
cli.run(["auth"]) is missing an assertion for the Pending backoff, so it would
still pass if the polling sleep were removed. Update this spec to expect the
injected sleeper double to receive sleep(1) during the pending-to-success path,
alongside the existing token write expectation, so the polling behavior in
cli.run and the auth client handling remains covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4eae52e1-a89a-4f8a-a27f-85f2ee2688f7

📥 Commits

Reviewing files that changed from the base of the PR and between 0796e83 and 19ae87d.

📒 Files selected for processing (6)
  • lib/slidict.rb
  • lib/slidict/auth_client.rb
  • lib/slidict/cli.rb
  • lib/slidict/credentials.rb
  • spec/slidict/cli_spec.rb
  • spec/slidict/credentials_spec.rb

{
device_code: fetch!(response, "device_code"),
user_code: fetch!(response, "user_code"),
verification_uri: response["verification_uri"] || "#{base_url}/cli/activate",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

verification_uri のフォールバック生成は URI.join を使った方が安全です。

"#{base_url}/cli/activate" だと、SLIDICT_AUTH_BASE_URL が末尾 / 付きやサブパス付きの値だった場合に //cli/activate/api/cli/activate になり、同じクラス内の post_json が使っている URL 解決とズレます。

修正例
-        verification_uri: response["verification_uri"] || "#{base_url}/cli/activate",
+        verification_uri: response["verification_uri"] || URI.join(base_url, "/cli/activate").to_s,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/auth_client.rb` at line 25, `AuthClient` の `verification_uri`
フォールバックが文字列連結になっており、`base_url` の末尾スラッシュやサブパスで不正な URL
になる可能性があります。`AuthClient#initialize` 内の `verification_uri` 生成を、同クラスの `post_json`
と同じ URL 解決方針に合わせて `URI.join` ベースに置き換え、`SLIDICT_AUTH_BASE_URL` の値に依存せず安全に
`cli/activate` を組み立てるよう修正してください。

Comment on lines +39 to +40
error = response["error"].to_s
raise Pending if %w[authorization_pending slow_down].include?(error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

slow_downauthorization_pending と同一視するとバックオフできません。

ここで両方とも Pending に潰しているため、CLI#auth 側は常に元の interval で再試行し続けます。レート制限に入ったケースでポーリング間隔を伸ばせず、認証完了前にタイムアウトしやすくなります。

修正の方向性
   class AuthClient
     Error = Class.new(StandardError)
     Pending = Class.new(StandardError)
+    SlowDown = Class.new(StandardError)
@@
-      raise Pending if %w[authorization_pending slow_down].include?(error)
+      raise Pending if error == "authorization_pending"
+      raise SlowDown if error == "slow_down"
# CLI#auth 側で SlowDown を rescue して待機時間を増やす
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/auth_client.rb` around lines 39 - 40, `AuthClient` では
`authorization_pending` と `slow_down` を同じ `Pending`
にまとめないよう修正してください。`AuthClient#...` の `response["error"]` 判定で `slow_down`
は別例外(または別の戻り値)に分け、`CLI#auth` 側でそれを rescue
して次回の待機時間を増やすバックオフ処理を入れてください。`authorization_pending` は従来どおり `Pending`
のままにし、`slow_down` だけポーリング間隔を伸ばせるようにしてください。

Comment thread lib/slidict/cli.rb
Comment on lines +145 to +160
token = client.poll_token(device_code: device[:device_code])
path = credentials.write_cli_token!(
access_token: token.fetch("access_token"),
token_type: token.fetch("token_type", "Bearer"),
provider: token.fetch("provider", "github")
)
@output.puts "4. Saved CLI access token to #{path}"
return 0
rescue AuthClient::Pending
return login_expired if Time.now >= deadline

@sleeper.sleep(device[:interval])
end
rescue AuthClient::Error, KeyError => e
@output.puts "Error: GitHub auth failed (#{e.message})"
1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

認証情報の保存失敗が未処理で、slidict auth が例外終了します。

credentials.write_cli_token! は権限不足やディスクフルで SystemCallError を投げうるのに、このメソッドはそれを rescue していません。ネットワークは成功しても保存時にスタックトレースで落ちるので、ここもユーザー向けエラーに畳んで 1 を返したいです。

修正例
-    rescue AuthClient::Error, KeyError => e
+    rescue AuthClient::Error, KeyError, SystemCallError => e
       `@output.puts` "Error: GitHub auth failed (#{e.message})"
       1
     end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
token = client.poll_token(device_code: device[:device_code])
path = credentials.write_cli_token!(
access_token: token.fetch("access_token"),
token_type: token.fetch("token_type", "Bearer"),
provider: token.fetch("provider", "github")
)
@output.puts "4. Saved CLI access token to #{path}"
return 0
rescue AuthClient::Pending
return login_expired if Time.now >= deadline
@sleeper.sleep(device[:interval])
end
rescue AuthClient::Error, KeyError => e
@output.puts "Error: GitHub auth failed (#{e.message})"
1
token = client.poll_token(device_code: device[:device_code])
path = credentials.write_cli_token!(
access_token: token.fetch("access_token"),
token_type: token.fetch("token_type", "Bearer"),
provider: token.fetch("provider", "github")
)
`@output.puts` "4. Saved CLI access token to #{path}"
return 0
rescue AuthClient::Pending
return login_expired if Time.now >= deadline
`@sleeper.sleep`(device[:interval])
end
rescue AuthClient::Error, KeyError, SystemCallError => e
`@output.puts` "Error: GitHub auth failed (#{e.message})"
1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/cli.rb` around lines 145 - 160, The `slidict auth` flow only
rescues `AuthClient::Error` and `KeyError`, so failures from
`credentials.write_cli_token!` can still crash with `SystemCallError`. Update
the `Slidict::CLI` auth path to catch save-time OS errors around
`credentials.write_cli_token!`, convert them into a user-facing `@output.puts
"Error: ..."` message, and return `1` just like the existing auth failures.

abechan1 and others added 2 commits June 27, 2026 23:09
Lets the CLI manage slides on slidict.io via the CLI access token saved
by `slidict auth`: list/show existing slides, and create or edit drafts
(slides API never allows publishing from the CLI).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The device token endpoint returns a non-2xx status with an
authorization_pending/slow_down body while polling, so post_json must
return that body instead of raising before poll_token can check it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
spec/slidict/credentials_spec.rb (1)

25-43: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

破損した認証ファイルの分岐も spec で固定しておきたいです。

lib/slidict/credentials.rb の Line 28-37 では、不正 JSON と kind 不一致を nil に落としていますが、この spec ではその 2 分岐が未カバーです。壊れた credentials.json で CLI が再び落ちる回帰を防ぐため、ここも追加しておくと安心です。

🧪 追加イメージ
   describe "`#read_cli_token`" do
+    it "returns nil for malformed JSON" do
+      Dir.mktmpdir do |dir|
+        path = File.join(dir, "slidict", "credentials.json")
+        File.write(path, "{")
+        credentials = described_class.new(path: path)
+
+        expect(credentials.read_cli_token).to be_nil
+      end
+    end
+
+    it "returns nil for non CLI token credentials" do
+      Dir.mktmpdir do |dir|
+        path = File.join(dir, "slidict", "credentials.json")
+        File.write(path, JSON.generate("kind" => "web_session", "access_token" => "cli-token"))
+        credentials = described_class.new(path: path)
+
+        expect(credentials.read_cli_token).to be_nil
+      end
+    end
+
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@spec/slidict/credentials_spec.rb` around lines 25 - 43,
`Credentials#read_cli_token` の未カバー分岐を spec に追加し、不正な JSON と `kind` 不一致のときに `nil`
を返す挙動を固定してください。`described_class.new` と `read_cli_token` を使い、壊れた
`credentials.json` と期待外の `kind` をそれぞれ用意して、例外にならず `nil` になることを確認するテストを
`#read_cli_token` の describe 内に追加してください。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/slidict/credentials.rb`:
- Around line 28-36: The read_cli_token method only rescues JSON::ParserError,
so File.read failures after File.exist? can still crash slidict slides with a
SystemCallError. Update read_cli_token in lib/slidict/credentials.rb to also
handle I/O-related exceptions from File.read, either by returning nil as an
unauthenticated state or converting them into the appropriate domain error,
while keeping the existing JSON parsing and token shape checks intact.

In `@lib/slidict/slides_command.rb`:
- Around line 40-45: The argument parsing logic is rejecting any value that
starts with “-”, so valid strings like `--body "- item"` and `--title "-draft"`
are being treated as missing. Update `fetch_value!`/the option parsing path in
`parse_list` and the related code around the body/title handling to only treat
known switch names as absent values, not all dash-prefixed strings. Keep the
`--page` integer validation separate in `parse_list` so page-specific checks
still reject invalid numbers without blocking legitimate text values.
- Around line 150-153: `read_body` の `File.read` で発生する `Errno::ENOENT` や
`Errno::EACCES` が `run` で拾われず CLI が異常終了する問題を修正してください。`SlidesCommand#read_body`
でファイル読み込み失敗を捕捉してユーザー向けのエラーメッセージに変換し、`SlidesCommand#run` 側で `ArgumentError` と同様に
exit 1 へ落とせるようにしてください。`read_body`、`run`、`options[:file]` の分岐を目印に実装してください。

---

Nitpick comments:
In `@spec/slidict/credentials_spec.rb`:
- Around line 25-43: `Credentials#read_cli_token` の未カバー分岐を spec に追加し、不正な JSON と
`kind` 不一致のときに `nil` を返す挙動を固定してください。`described_class.new` と `read_cli_token`
を使い、壊れた `credentials.json` と期待外の `kind` をそれぞれ用意して、例外にならず `nil` になることを確認するテストを
`#read_cli_token` の describe 内に追加してください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b3ec8869-d4f8-4974-83fd-a308d9c222de

📥 Commits

Reviewing files that changed from the base of the PR and between 19ae87d and 6305c2b.

📒 Files selected for processing (12)
  • AGENTS.md
  • README.md
  • lib/slidict.rb
  • lib/slidict/auth_client.rb
  • lib/slidict/cli.rb
  • lib/slidict/credentials.rb
  • lib/slidict/slides_client.rb
  • lib/slidict/slides_command.rb
  • spec/slidict/cli_spec.rb
  • spec/slidict/credentials_spec.rb
  • spec/slidict/slides_client_spec.rb
  • spec/slidict/slides_command_spec.rb
✅ Files skipped from review due to trivial changes (3)
  • AGENTS.md
  • README.md
  • lib/slidict.rb

Comment on lines +28 to +36
def read_cli_token
return nil unless File.exist?(@path)

data = JSON.parse(File.read(@path))
return nil unless data["kind"] == "cli_access_token" && data["access_token"]

{ access_token: data["access_token"], token_type: data.fetch("token_type", "Bearer") }
rescue JSON::ParserError
nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

認証ファイルの読み取り失敗が slidict slides を例外終了させます。

ここは JSON::ParserError しか rescue していないので、File.exist? 後の削除や権限エラーで File.readSystemCallError を投げると、そのまま CLI が落ちます。少なくともこのメソッド内で I/O 失敗も吸収して、未認証扱いかドメインエラーへ変換した方が安全です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/credentials.rb` around lines 28 - 36, The read_cli_token method
only rescues JSON::ParserError, so File.read failures after File.exist? can
still crash slidict slides with a SystemCallError. Update read_cli_token in
lib/slidict/credentials.rb to also handle I/O-related exceptions from File.read,
either by returning nil as an unauthenticated state or converting them into the
appropriate domain error, while keeping the existing JSON parsing and token
shape checks intact.

Comment on lines +40 to +45
def parse_list(args)
options = { subcommand: :list }
until args.empty?
case (arg = args.shift)
when "--page" then options[:page] = Integer(fetch_value!(args, arg))
when "-h", "--help" then options[:help] = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

--body "- item" のような正当な値を未指定扱いしてしまいます。

Line 92 が先頭 - の値を一律で弾いているので、--body "- item"--title "-draft" が通りません。既知のスイッチ名だけを未指定扱いにして、--page の正数チェックは Line 44 側で分けた方が安全です。

💡 修正イメージ
     def parse_list(args)
       options = { subcommand: :list }
       until args.empty?
         case (arg = args.shift)
-        when "--page" then options[:page] = Integer(fetch_value!(args, arg))
+        when "--page"
+          page = Integer(fetch_value!(args, arg))
+          raise ArgumentError, "--page must be >= 1" if page < 1
+          options[:page] = page
         when "-h", "--help" then options[:help] = true
         else raise ArgumentError, "unknown option #{arg}"
         end
       end
       options
@@
     def fetch_value!(args, option)
       value = args.shift
-      raise ArgumentError, "#{option} requires a value" if value.nil? || value.start_with?("-")
+      known_switches = %w[--page --title --body --file --body-format --visibility -h --help]
+      raise ArgumentError, "#{option} requires a value" if value.nil? || known_switches.include?(value)

       value
     end

Also applies to: 90-95

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/slides_command.rb` around lines 40 - 45, The argument parsing
logic is rejecting any value that starts with “-”, so valid strings like `--body
"- item"` and `--title "-draft"` are being treated as missing. Update
`fetch_value!`/the option parsing path in `parse_list` and the related code
around the body/title handling to only treat known switch names as absent
values, not all dash-prefixed strings. Keep the `--page` integer validation
separate in `parse_list` so page-specific checks still reject invalid numbers
without blocking legitimate text values.

Comment on lines +150 to +153
def read_body(options)
return File.read(options[:file]) if options[:file]

options[:body]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

--file の読み取り失敗がそのまま異常終了になります。

Line 151 の File.readErrno::ENOENTErrno::EACCES が出ると、runArgumentError しか拾わないため、そのまま CLI が落ちます。ここはユーザー向けエラーに変換して exit 1 に寄せたいです。

💡 修正イメージ
     def read_body(options)
-      return File.read(options[:file]) if options[:file]
+      return File.read(options[:file]) if options[:file]

       options[:body]
+    rescue SystemCallError => e
+      raise ArgumentError, "could not read #{options[:file]}: #{e.message}"
     end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def read_body(options)
return File.read(options[:file]) if options[:file]
options[:body]
def read_body(options)
return File.read(options[:file]) if options[:file]
options[:body]
rescue SystemCallError => e
raise ArgumentError, "could not read #{options[:file]}: #{e.message}"
end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/slides_command.rb` around lines 150 - 153, `read_body` の
`File.read` で発生する `Errno::ENOENT` や `Errno::EACCES` が `run` で拾われず CLI
が異常終了する問題を修正してください。`SlidesCommand#read_body`
でファイル読み込み失敗を捕捉してユーザー向けのエラーメッセージに変換し、`SlidesCommand#run` 側で `ArgumentError` と同様に
exit 1 へ落とせるようにしてください。`read_body`、`run`、`options[:file]` の分岐を目印に実装してください。

abechan1 and others added 3 commits June 28, 2026 19:38
Lets the main `slidict` command save the generated deck straight to
slidict.io as a draft via --publish (create) or --slide-id (edit an
existing draft), reusing SlidesClient/SlidesCommand. Adds a public
SlidesCommand#publish entry point that skips argv parsing entirely,
since the rendered body often starts with "---" (YAML frontmatter)
which the CLI-style "looks like a flag" check would otherwise reject.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: bump version to v0.2.0

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/slidict/cli.rb`:
- Around line 202-203: `body_format_for` の正規化ルールと `MarkdownRenderer#render`
の判定条件が一致していません。`body_format_for` と `MarkdownRenderer#render`
の両方で同じ正規化結果を使うように統一し、`framework` の大小文字や表記ゆれでも `asciidoctor-revealjs`
の扱いが同じになるよう修正してください。`body_format_for`、`MarkdownRenderer#render`、および `framework`
の比較ロジックを合わせて、本文形式の決定と実際のレンダリング分岐が矛盾しないようにしてください。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e179354e-e833-49c1-af20-361d59ec1030

📥 Commits

Reviewing files that changed from the base of the PR and between 6305c2b and c22589b.

📒 Files selected for processing (5)
  • README.md
  • lib/slidict/cli.rb
  • lib/slidict/slides_command.rb
  • spec/slidict/cli_spec.rb
  • spec/slidict/slides_command_spec.rb
✅ Files skipped from review due to trivial changes (2)
  • README.md
  • spec/slidict/slides_command_spec.rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/slidict/slides_command.rb

Comment thread lib/slidict/cli.rb
Comment on lines +202 to +203
def body_format_for(framework)
framework.to_s.downcase == "asciidoctor-revealjs" ? "asciidoc" : "markdown"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

body_format と実際のレンダリング形式を同じ正規化ルールにしてください。

body_format_for は大小文字を無視しますが、MarkdownRenderer#render"asciidoctor-revealjs" の完全一致で分岐します。--framework Asciidoctor-RevealJS のような入力では Markdown 本文を asciidoc として publish し得ます。

修正例
-      options[:output] ||= default_output_for(options[:framework])
+      options[:framework] = options[:framework].to_s.downcase
+      options[:output] ||= default_output_for(options[:framework])
       options
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/slidict/cli.rb` around lines 202 - 203, `body_format_for` の正規化ルールと
`MarkdownRenderer#render` の判定条件が一致していません。`body_format_for` と
`MarkdownRenderer#render` の両方で同じ正規化結果を使うように統一し、`framework` の大小文字や表記ゆれでも
`asciidoctor-revealjs`
の扱いが同じになるよう修正してください。`body_format_for`、`MarkdownRenderer#render`、および `framework`
の比較ロジックを合わせて、本文形式の決定と実際のレンダリング分岐が矛盾しないようにしてください。

--publish (and `slidict slides create/edit`) used to fail with a bare
"Error: invalid_token" or "not authenticated" message. Now SlidesCommand
triggers the existing `slidict auth` device-login flow automatically and
retries once when the token is missing or rejected by the API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@abechan1 abechan1 merged commit 6ac8306 into main Jun 28, 2026
5 checks passed
@abechan1 abechan1 deleted the revert-25-revert-23-codex/implement-github-authentication-for-cli branch June 28, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant