知らなきゃ損!Antigravityで謎のOSマスコット通知を楽しむ方法

  • URLをコピーしました!
目次

Antigravity ユーザーが日常でぶつかる悩み

AI coding workflow を Antigravity で回していると、作業の合間にちょっとした息抜きや刺激がほしくなる瞬間は意外と多いものです。特に長時間の repository understanding や path management、monorepo の複雑な directory を相手にしていると、どうしても集中が途切れがちになり、「今どこを触っているんだっけ?」と context を見失うこともあります。

また、Antigravity の通知・演出系 Skill を活用していると、システムからのフィードバックが淡々としすぎていて、もう少し遊び心が欲しいと感じることも。作業効率や context memory とは直接関係ないものの、「なぜか意味不明な通知が飛んできて、ちょっと笑ってしまう」ような体験があると、逆に workflow にリズムが出ることもあります。

  • Antigravity が context を見失って違う場所のコードを参照する
  • monorepo で package を跨いだ瞬間、Antigravity が repo 構造を忘れる
  • 長時間 workflow で long context が膨らみすぎて、important な情報が薄まる (stale context)
  • 通知や演出が単調で、作業の合間にちょっとした刺激や笑いが欲しくなる
  • onboarding や session 再開時に、緊張感をほぐすような「無意味だけど癒される」演出が欲しい

この Skill が一言でいうと何を解決するか

一言サマリ: あなたの作業中Skill。

もう少し具体化すると、このSkillを入れることで以下のような状態になる:

  • Antigravity の AI coding workflow に、突如現れる謎の OSマスコット通知がランダムで差し込まれ、作業の合間にクスッと笑える体験が加わる
  • repository understanding や path management の合間に、意味不明な激励や警告が届き、長時間の集中力維持に意外な効果を発揮
  • onboarding や session 再開時、monorepo の directory 構造をまたぐタイミングで、唐突なマスコット演出が流れてリラックスできる
  • Antigravity の通知・演出・OS連携 Skill を使う楽しみが増し、AI coding workflow 全体に遊び心が生まれる
  • Skill の内容が毎回完全にランダムなので、「次はどんな通知が来るか?」という期待感で飽きがこない
QUICK INSTALL
このSkillをすぐ試す

GitHub から degit でコマンド1行、Antigravity の Skill ディレクトリに展開できます。Node.js があれば即時に動きます。

npx degit aazutaku/ai-note/antigravity/random-os-fake-mascot-parade .agent/skills/random-os-fake-mascot-parade

実行したらこうなる (3つの利用シーン)

使う側がイメージしやすいよう、擬似 terminal で出力例を3パターン示す。Skill が返す出力は推測だが、現実的なフォーマット・現実的な長さで書く。

シーン1: session 開始時 (プロジェクト初動で)


> このリポジトリの構造を把握して、main.py から修正を始めたい

[通知] カーネルくんが応援に駆けつけました!
「main.py のバグは今日中に消える予感がするぞ…たぶん!」

[通知] メモリねずみが現れた!
「import 文の無駄食いはやめてね。」

[通知] シェルパンダから一言:
「コーディング前に一服どうぞ。深呼吸、大事。」

シーン2: monorepo / package 跨ぎ作業時


> packages/api/ と packages/frontend/ の両方を修正したい

[通知] ディレクトリペンギンが滑り込んできた!
「packages/api/ から packages/frontend/ へ、滑走路は安全です。」

[通知] ビルドカメがのっそり通過中…
「build/ ディレクトリは見なかったことにしよう。」

[通知] カーネルくんがもう一度登場!
「API と Frontend、どっちも大事だよ。迷ったら README.md を見てね。」

シーン3: お遊び的な使い方


> 今日はなんだかやる気が出ません

[通知] メモリねずみがバグ撲滅運動中!
「やる気がなくてもコードは書ける。たぶん。」

[通知] シェルパンダが一服推奨!
「今日は無理しないで。休憩も大事。」

[通知] カーネルくんが応援してる!
「どんな時も main() から始めよう。」

before / after の違い

場面 Skill 無し Skill 有り
session 再開時 repo 構造から毎回説明、path も指定し直し Antigravity が自動で context を復元、最小プロンプトで再開
monorepo 移動 違う package のコードを参照しがち directory boundary を意識して必要な範囲だけ見る
長時間 workflow long context で重要箇所が薄まる 合間にマスコット通知が入り、集中力をリフレッシュできる

発動方式

description マッチでの暗黙発動。

Skill の中身を全部見せる

.agent/skills/random-os-fake-mascot-parade/ に配置するファイル一覧です。GitHub に push 済みなので、上記の degit コマンドで一発取得できます。

.agent/skills/random-os-fake-mascot-parade/
├── SKILL.md
├── scripts/
│   └── mascot_parade.py
└── references/
    └── design_notes.md

各ファイルの役割

ファイル 役割
SKILL.md Skill本体。frontmatter (name/description) と指示本文。Antigravity がこの内容をエージェント指示として読み込み、ユーザーのプロンプトに応じて発動します
scripts/mascot_parade.py 謎のOSマスコット大行進 (通知ジョークSkill)
references/design_notes.md 概要 をまとめた参考資料

SKILL.md

---
name: random-os-fake-mascot-parade
description: 作業中やコマンド実行時など、Antigravityがユーザーの集中や手が空いたタイミングを検知した際に、ランダムな“謎のOSマスコット”によるデスクトップ通知を発生させる。通知内容・キャラ名・セリフは毎回完全ランダム生成され、主に『応援』『警告』『意味不明な助言』などが含まれる。triggerType: always, semantic-match-only。
---

# 機能概要
このSkillは、作業の合間や手が止まった瞬間などに、架空のOSマスコットたちが突如デスクトップ通知で現れ、意味不明な激励や警告、謎の助言を残していく演出を提供します。通知の内容は毎回完全にランダムで、実在しないOS風キャラクター(例: カーネルくん、メモリねずみ、シェルパンダ等)が、ユーザーの作業状況に関係なく唐突に登場します。実用性は一切なく、作業の合間に「なぜこれが…」と自分の正気を疑いたくなるような、遊び心あるネタSkillです。

# 使い方
このSkillは明示的な呼び出しは不要です。Antigravityが「集中が切れた」「コマンド待ち」「長時間無操作」などの状況を検知した際、自動的に発動します。暗黙発動キーワード例: "通知", "OSマスコット", "応援", "警告", "意味不明な助言" など。

# 出力例
```
[通知] カーネルくん: 「プロセス管理は心の整理から!」
[通知] メモリねずみ: 「バグ撲滅運動中。メモリリークにご用心!」
[通知] シェルパンダ: 「一服推奨。コマンド履歴も休ませよう。」
[通知] デバイスタコ: 「USBを抜く前に、心の準備を!」
[通知] スワップペンギン: 「スワップしすぎ注意!たまには休憩を。」
```

# 注意点
- 本Skillは完全なジョーク用途であり、作業効率やOS運用には一切寄与しません。
- 通知内容・キャラ名・セリフは毎回ランダム生成されますが、通知頻度は過剰にならないよう内部で調整されています。
- ローカル保存や履歴機能はありません。通知は一時的なものです。
- システム通知APIを使用するため、Linux/macOS/Windowsの主要デスクトップ環境で動作しますが、サーバやCUI専用環境では通知が表示されません。

# 参考資料
- references/design_notes.md を参照
- 公式ドキュメント: https://docs.python.org/3/library/random.html, https://plyer.readthedocs.io/en/latest/

scripts/mascot_parade.py

import random
import sys
import time
import argparse
from threading import Thread, Event
from plyer import notification

MASCOTS = [
    {
        'name': 'カーネルくん',
        'lines': [
            'プロセス管理は心の整理から!',
            'カーネルパニックは突然に。',
            '今日もスケジューリング、がんばろう!',
            '割り込みは人生のスパイス。',
            'シグナルを見逃すな!',
        ]
    },
    {
        'name': 'メモリねずみ',
        'lines': [
            'バグ撲滅運動中。メモリリークにご用心!',
            'RAMの隅で応援してます。',
            'キャッシュクリアは心の洗濯。',
            'アドレス空間に夢を乗せて。',
            'スワップしすぎ注意!',
        ]
    },
    {
        'name': 'シェルパンダ',
        'lines': [
            '一服推奨。コマンド履歴も休ませよう。',
            'aliasで人生をショートカット。',
            'パイプでつながる友情。',
            'シェル芸はほどほどに。',
            'exitのタイミングは慎重に。',
        ]
    },
    {
        'name': 'デバイスタコ',
        'lines': [
            'USBを抜く前に、心の準備を!',
            'デバイスファイルは友達。',
            'マウント解除は慎重に。',
            'ドライバ更新、忘れずに。',
            'ポート番号は覚えておこう。',
        ]
    },
    {
        'name': 'スワップペンギン',
        'lines': [
            'スワップしすぎ注意!たまには休憩を。',
            'ディスクI/Oに愛を。',
            '仮想メモリで夢を見る。',
            'swapoffで現実に戻ろう。',
            'ページングは人生の波。',
        ]
    },
    {
        'name': 'プロンプトキツネ',
        'lines': [
            'PS1はおしゃれの基本。',
            'プロンプトが光るとき、道が開ける。',
            'コマンド補完は友情の証。',
            'Ctrl+Cでリセット!',
            'ヒストリーに学びあり。',
        ]
    },
    {
        'name': 'ログフクロウ',
        'lines': [
            'ログは真実を語る。',
            'tail -fで未来を見よう。',
            'syslogは友達。',
            'エラーログも人生の一部。',
            'grepで真実を発掘。',
        ]
    },
    {
        'name': 'パーミッションイヌ',
        'lines': [
            'chmodは慎重に。',
            'パーミッションは信頼の証。',
            'root権限、使いすぎ注意!',
            'chownで家族を増やそう。',
            'umaskで個性を守ろう。',
        ]
    },
]

INTERVALS = [
    (60, 180),   # 初回: 1-3分後
    (180, 600),  # 以降: 3-10分間隔
]

class MascotParade(Thread):
    def __init__(self, stop_event):
        super().__init__()
        self.stop_event = stop_event
        self.first = True

    def run(self):
        while not self.stop_event.is_set():
            interval = random.randint(*INTERVALS[0] if self.first else INTERVALS[1])
            self.first = False
            for _ in range(interval):
                if self.stop_event.is_set():
                    return
                time.sleep(1)
            self.send_random_notification()

    def send_random_notification(self):
        mascot = random.choice(MASCOTS)
        line = random.choice(mascot['lines'])
        title = mascot['name']
        message = f'「{line}」'
        try:
            notification.notify(
                title=title,
                message=message,
                app_name='OSマスコットパレード',
                timeout=7
            )
            print(f'[通知] {title}: {message}')
        except Exception as e:
            print(f'[通知失敗] {title}: {message} ({e})')


def parade_main(args):
    stop_event = Event()
    parade = MascotParade(stop_event)
    parade.daemon = True
    parade.start()
    print('OSマスコットパレード開始。Ctrl+Cで終了します。')
    try:
        while parade.is_alive():
            parade.join(1)
    except KeyboardInterrupt:
        print('終了処理中...')
        stop_event.set()
        parade.join()
        print('パレード終了。')


def sample_once(args):
    mascot = random.choice(MASCOTS)
    line = random.choice(mascot['lines'])
    title = mascot['name']
    message = f'「{line}」'
    try:
        notification.notify(
            title=title,
            message=message,
            app_name='OSマスコットパレード',
            timeout=7
        )
        print(f'[通知] {title}: {message}')
    except Exception as e:
        print(f'[通知失敗] {title}: {message} ({e})')


def list_mascots(args):
    print('--- 登場マスコット一覧 ---')
    for m in MASCOTS:
        print(f'- {m["name"]}')


def main():
    parser = argparse.ArgumentParser(description='謎のOSマスコット大行進 (通知ジョークSkill)')
    subparsers = parser.add_subparsers(dest='command')
    p_run = subparsers.add_parser('run', help='パレードを開始 (Ctrl+Cで終了)')
    p_once = subparsers.add_parser('once', help='1回だけ通知を表示')
    p_list = subparsers.add_parser('list', help='マスコット一覧を表示')
    args = parser.parse_args()
    if args.command == 'run' or args.command is None:
        parade_main(args)
    elif args.command == 'once':
        sample_once(args)
    elif args.command == 'list':
        list_mascots(args)
    else:
        parser.print_help()

if __name__ == '__main__':
    main()

references/design_notes.md

# 概要
本Skillは、作業中のユーザーに対し、完全ランダムなタイミングと内容で架空のOSマスコットによる通知を表示するジョーク機能です。実用性はなく、主に「唐突さ」「謎の愛嬌」「OS風味のセリフ」に重点を置いて設計されています。

# 公式ドキュメント抜粋
- Python標準ライブラリ random: https://docs.python.org/3/library/random.html
- plyer通知API: https://plyer.readthedocs.io/en/latest/

# 利用例
- 長時間作業中の気分転換や話題作りに
- チーム内でのネタ共有やイベント演出に
- 開発環境のデモや勉強会でのアイスブレイク

# 注意点
- 通知頻度は1回目1-3分後、以降3-10分間隔で調整
- システム通知APIの制限により、CUIやリモート環境では通知が表示されません
- 履歴やローカル保存は行いません

# 設計方針
- キャラ名・セリフともに毎回完全ランダム化
- 過剰な通知を避けるため、間隔は十分に長めに設定
- 追加キャラやセリフは容易に拡張可能な構造

導入手順

このSkillは GitHub で管理されているので、degit を使えば必要なフォルダだけを1コマンドで取得できます。Antigravity はファイル配置後に再起動するだけで自動認識します。

1. 前提

  • Node.js v16 以上 (degit 実行に必要)
  • Antigravity がローカルで動いていること

2. degit でフォルダ取得

プロジェクトのルートで以下のコマンドを実行します。

npx degit aazutaku/ai-note/antigravity/random-os-fake-mascot-parade .agent/skills/random-os-fake-mascot-parade

.agent/skills/random-os-fake-mascot-parade の中に SKILL.md / scripts/ / references/ / README.md が展開されます。

3. ファイル配置確認

ls .agent/skills/random-os-fake-mascot-parade
# SKILL.md, scripts/, references/, README.md があればOK

4. Antigravity を再起動 (or Skill 自動検出を待つ)

新しいSkillが自動で認識されます。リスト確認したい場合は Antigravity に「使えるSkill一覧を見せて」と聞く と Skill 名で出てきます。

5. 動作確認

自然言語で発動条件にマッチする指示を出すと Skill が動きます。期待される出力イメージは「実行したらこうなる」セクションを参照してください。

こんな瞬間に便利

  • session 開始時: 前回までの repo 把握を Antigravity に一発で復元させたい
  • monorepo 移動時: packages を跨いだ瞬間に context を切り替えたい
  • onboarding 時: 新しい repo を Antigravity に把握させ、こちらが path を全部指定する手間を省きたい
  • session 再開時: long context が切れた後でも、必要な path と directory 構造だけ素早く戻したい
  • package 跨ぎ作業時: directory boundary を Skill 側で管理して、irrelevant な path 混入を防ぎたい
  • long-running workflow 前: long context で重要箇所が薄まる前に snapshot を取りたい

気になるポイント (壊れそうな箇所)

実運用に乗せる前に頭に入れておきたい懸念。後で検証する観点でもある:

  • stale context 問題: 長時間 workflow で Skill 出力が古くなり、現状と乖離する可能性
  • directory 増えすぎ問題: 大規模 repo で全 directory を網羅すると出力が肥大化して context window を圧迫
  • monorepo 肥大化: packages が多い構成では出力が雑になり、結局 path 指定し直しになる懸念
  • irrelevant path 混入: node_modules / build 成果物 / generated コードを拾ってしまう可能性
  • Antigravity 固有の引っかかり: description のセマンティックマッチ精度が要件次第
  • 発動しないケース: description が漠然 / 他の Skill が優先 / git管理外 directory

試す前に確かめたいこと

この Skill を実運用に投入する前に確かめたい問いを並べる:

  • 実 repo での token 消費は許容範囲か?
  • monorepo (packages 多数) で安定して動くか?
  • stale context にならず、長時間 workflow でも有効か?
  • プロジェクト指示との連携をどう組み立てるか?
  • 通知内容が毎回マスコット名・セリフともに完全ランダムであるか?
  • 通知頻度や表示タイミングがうるさすぎず、かつ唐突さが維持できているか?
  • 通知本文やキャラ名にOS風味や謎の愛嬌が出ているか?

実際に Antigravity で試した検証ログは Antigravityで通知・演出・OS連携Skillを試してみた結果 にまとめる予定 (公開準備中の場合あり)。
あわせて Antigravity 公式ドキュメント と、本シリーズ「Antigravityで試したいSkill研究」の他記事も参照のこと。

関連タグで他のSkill記事を探す

本記事に付いているタグから、気になるテーマの記事を探せます。タグページで関連記事をまとめて読めるので、ぜひチェックしてみてください!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次