Raycastの拡張機能を作った時のメモ

## 作った拡張機能の紹介

Raycastの拡張機能を入れておけば、アクティブなタブのリンクを好きなフォーマット(PlainText/Markdown/HTML)でコピーしてくれるやつです。

https://raycast.com/sinsky/create-link

↓デモ用なので入力していますが、皆様ご存知のHotkeyに登録しておけばクッソ楽

![デモGIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/3c6ae6f2-a2c0-466f-ad9c-ebda15559de6.gif)

それぞれのブラウザの拡張機能で同じものはあると思うのですが、

- manifestの変更に対応する必要がある(v2からv3の置き換え問題とか...)
- Raycastのレビュープロセスを通すことでセキュリティ的にも安全(?)
- RaycastのHotKeyで管理することができる

といったことを踏まえると、自分で作ってRaycastで公開してもらう方が手っ取り早く安全だなと考えたわけです。
(ブラウザの拡張機能は良くも悪くもRaycastに依存してしまいますが)

`Create Link`という名前にしましたが、ありがちな機能すぎて良いネーミングは思い浮かびませんでした... 

## 作ってる最中に困ったこと

### ガイドラインの把握

これに尽きます。
というのも、機能自体がシンプルで他のライブラリを利用する必要もなかったので、作成自体は基本的なTypeScriptの知識でどうにかなりました。
何より、拡張機能は色々公開されているので公開されているコードを参考にしたり、AIとお友達になっておけば大きく困ることってないのかなと...

前述の通り、拡張機能は大量に公開されているので、貢献が少ないわけがないです。

なので、ちゃんとCONTRIBUTINGに記載はあります。
しかし、あまりこう言ったものにプルリクを出さない民としてはドキドキしてしまうわけで...

https://github.com/raycast/extensions/blob/main/CONTRIBUTING.md

:::note info
基本的には以下のサイトに目を通しておけばOK
https://developers.raycast.com
https://manual.raycast.com
:::

### 紹介スクリーンショットの添付

Raycastの拡張機能をStoreで見たことがある方はご存知かと思うのですが、
紹介用のスクリーンショットがある方が見栄えがいいのです...

![CleanShot 2025-03-21 at 15.43.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565925/0066c131-c329-49d5-8bfc-808afb138fe2.png)

https://developers.raycast.com/basics/prepare-an-extension-for-store#screenshots

そして、当然追加することをお勧めされます。(Botから)

とはいえ、今回は機能が機能なので、シンプルすぎてスクリーンショットは添付しませんでした。
※これで揉めごとが起きたとかは特にない

ただ突っ込まれるかはプルリクのレビューが通るまでドキドキでした...(小心者)

## 作った後に困ったこと

### Botによる変更をローカルに適用させる方法がわからない

#### 前提(プルリクまでの流れ)

普通にGit操作してたらわかるんですが、Raycastって自前でpublishまで用意してくれています。

なので、以下のコマンドでプルリク出すまではアッサリ

- ローカルでのテスト時
    - `npm install && npm run dev`
- 公開前の検証
    - `npm run lint`
    - `npm run build`
- 拡張機能の公開(プルリクの作成までやってくれる)
    - `npm run publish`

そうすると、自分のGitHubアカウントで、フォークからブランチの作成(`ext/create-link`)、
プルリクの下書きの作成までやってくれるわけです。

:::note info
publishに必要な流れはこの辺に書いてあります。
https://developers.raycast.com/basics/publish-an-extension
:::

あとは下書きの状態のプルリクの内容を完成させてプルリクを完成版にすればOK

ひと段落... :tea: 

と思いきや、今度はAIによるレビューが飛んできます。今時です。
Greptileというものを使っているようで、早速コメントが飛んできました。

https://github.com/apps/greptile-apps

https://www.greptile.com

Botの修正に同意すれば承認してあげれば適用してくれますが、
一部だけ改修したいとか、もっと別の案で改修しようとしたら自分で修正する必要があります。

### 問題点

`npm run publish`でリポジトリ作ってくれてるわけなんですが、
自分のローカルとはリモートリポジトリは繋がってないんです(多分)

なので、`git remote -v`をしてもリモートは登録されておらず、
すでに一部はBotによって修正を入れたため、pullしておかないとコンフリクトが発生する...
というカオスな事態

### 解決策

この状態での反映方法がわからず、パッと探してもわからない私はフォークしたリポジトリを再度持ってくる方法を選びました。

```shell
git clone git@github.com:sinsky/raycast-extensions.git
cd raycast-extensions/extensions/create-link
```

でやればいいじゃん、と思うのも束の間
リポジトリがデカすぎて、cloneに時間がめっっっちゃかかる

ということであまり使ったことのない、sparse-checkoutを利用(多分こんな感じだったはず)

```shell
git clone --no-checkout --filter=blob:none git@github.com:sinsky/raycast-extensions.git
cd raycast-extensions
git sparse-checkout set extensions/create-link
git branch
git checkout ext/create-link
```

これで自分の拡張機能だけの、軽いフォルダが出来上がります。
[DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)の時は使い方わからず諦めていたので、ようやく使いこなせそうです(遅)

### 本当の解決策(公式的な)

いやいや、そんなはずないやろ・・・
と後から思いました(というよりも解決策を探る余裕がなかった)

ということで公式が提供している`ray`の機能を調べていくと、`pull-contributions`というものが見つかりました...

```shell
> npx ray --help    
Build extensions for Raycast with React and Node.js.

VERSION
  @raycast/api/1.94.0 darwin-arm64 node-v20.16.0

USAGE
  $ ray [COMMAND]

COMMANDS
  autocomplete        Display autocomplete installation instructions.
  build               Build the extension to the output directory
  dev                 Start the extension in development mode and watches for changes
  develop             Start the extension in development mode and watches for changes
  evals               Run AI evals defined in extension package.json
  help                Display help for ray.
  lint                Validate the extension manifest and metadata, and lint its source code
  login               Log into your Raycast account
  logout              Log out of your Raycast account
  migrate             Migrate the extension to a newer version of the Raycast API
  profile             Show profile of the currently logged in user
  publish             Publish the extension
  pull-contributions  Pull contributions of the extension
  token               Display the access token
  version             Print the version number
```
```shell
> npx ray pull-contributions --help
Pull contributions of the extension

USAGE
  $ ray pull-contributions [--exit-on-error] [--emoji] [--help] [-I]

GLOBAL FLAGS
  -I, --non-interactive     Disable interactive outputs, useful for CI
      --emoji               Prefix output with emojis 🌈
      --[no-]exit-on-error  Always exit with non-zero code on error
      --help                Show the help message for the command

DESCRIPTION
  Pull contributions of the extension
```

多分これ使えばよかっただけのお話でした。ハイ。
とはいえ、`sparse-checkout`の使い方がわかったのでよかった...

## 終わりに

ということで、誰に役立つのかわからない記事の出来上がりです(?)

Raycast拡張機能の開発としては初めてですが、色々用意してくれてるのでさすが開発者に喜ばれるアプリケーションだなと...

とりあえずシンプルな状態でリリースしましたが、あと考えている機能としては

- ユーザーがFromatをある程度自由に制御してコピー
    - `<{url}>` → `<https://...>` みたいな
    - 時間があったので実装終わりました:rocket: 
- 全てのタブをリスト化し、指定のタブをコピー
    - React使ってリスト化、選んだタブをplain,html,markdownでコピーできるイメージ
    - 一応別のブランチで作ってる最中(これを作るとスクショ貼れるので歓喜(?))

とかは欲しいかなと思いました。
遅くならない程度に更新していきたいな...

説明文も全部AIに頼りました(英語力皆無なため)
でももっとシンプルでいいかも:thinking: 

## 余談

Raycastのextensionsリポジトリは結構な頻度でプルリクが出てるみたいです。
Botからは最初のレビューに10~15営業日かかるよ〜と言われたのも納得...

iOSのベータ版が動いている模様、Windowsも待ち遠しい〜