OmniFocusを第二の脳にして自動化システムの通知ハブにしているよ!というお話

タスク管理アプリは数多くありますが、私が長年メインで使い続けているのが OmniFocus です。GTD(Getting Things Done)の思想を素直に体現できるアプリで、単なる「ToDoリスト」を超えた使い方ができるのが魅力です。

ちなみに私のメインPCは Windows で、OmniFocusは iOS版(iPhone)しか使っていません。OmniFocusというと「macOS + iOSのAppleエコシステム使いが本領」と思われがちですが、iOS版だけでも十分すぎるほど活躍してくれています。むしろ「常に手元にあるiPhoneがタスクハブになる」というスタイルは、Windows + iPhoneユーザーにこそハマる構成だと思っています。

今回は、私が普段OmniFocusをどう使っているか、そしてどんな風に他のツールと組み合わせて「自動化のハブ」にしているかをご紹介します。

OmniFocusとは

OmniFocus

OmniFocusは、Omni Groupが開発しているmacOS・iOS(iPadOS)向けのタスク管理アプリです。GTDの考え方をベースに、「プロジェクト」「アクション」「タグ」「パースペクティブ(ビュー)」「レビュー」といった概念で、頭の中のあらゆるタスクを整理できるよう設計されています。

シンプルなToDoアプリと違い、

  • 開始日・期限日・計画日を細かく設定できる
  • 繰り返しタスクのルールが柔軟(「前回完了から3日後」など)
  • プロジェクトやタグ、フォルダで多角的に分類できる
  • パースペクティブで「今日やるべきもの」だけを抽出できる

といった点が、日々のルーティン管理にも、長期プロジェクトの管理にも向いています。

Windows使いがiOS版だけで運用してみて

OmniFocusはApple純正環境前提のアプリなので、Windowsをメインに使っている人は最初ちょっと躊躇するかもしれません。私もそうでした。けれど結論から言うと、iOS版だけでも全く困っていません

理由はシンプルで、

  • タスク管理は「席にいる時」より「移動中・スキマ時間」に発生することが多い
  • iPhoneはいつも手元にある
  • 後述するiOSショートカット・Omni Automation・メールドロップとの組み合わせで、iPhone側だけで運用が回るようになる

という感じで、Windowsで作業しているときも「タスクの追加・確認はiPhoneに任せる」運用が自然にできています。

ちなみに OmniFocusにはWeb版もあって、Mac版に近い操作はWindowsからでも可能 です。ただしWeb版は 追加で月額料金が発生する ので、私は契約していません。Windows側からタスクを投げ込みたいときは、後述のメールドロップを使えば追加課金なしで十分まかなえてしまうので、Web版は今のところ必要性を感じていないという感じです。

私の使い方:始業前ルーティンを全部任せる

私の使い方の基本は、「考えるべきことを全部OmniFocusに預ける」 ことです。特に毎朝の始業前ルーティンは、ほぼOmniFocus任せにしています。

たとえば「ジョブカン打刻(タイムカード打刻)」のような毎日必ず発生するタスクは、繰り返しタスクとして登録しておき、朝のパースペクティブに自動で並ぶようにしています。これによって「あれやったっけ?」と頭で覚えておく必要がなくなり、出社準備の認知負荷がぐっと下がります。

詳しい運用は iOS版のTampermonkeyが登場したので出退勤時のタイムカード打刻(ジョブカン)を自動化してみたよ!というお話 にも書きました。

iOS版のTampermonkeyが登場したので出退勤時のタイムカード打刻(ジョブカン)を自動化してみたよ!というお話

パースペクティブ:OmniFocus最大のコア機能

OmniFocusを語るうえで 絶対に外せないコア機能 が、パースペクティブ(Perspective) です。ざっくり言うと、タスクを絞り込んで表示する保存済みビュー なのですが、ここがOmniFocusの真骨頂だと思っています。OmniFocus全体の使い心地を決めているのは、極論すればこのパースペクティブと言っても過言ではありません。

パースペクティブが強いのは、

  • 今表示させたいものを能動的に選べる(タグ・プロジェクト・期限・開始日・残り時間・状態 などの組み合わせ)
  • 逆に、今表示させたくないものを除外できる(特定タグ付きを隠す、特定プロジェクトを非表示、今日対象でないものを切り捨てる、など)

という 両方向のフィルタを同時にかけられる 点です。

OmniFocusには標準で「インボックス」「プロジェクト」「タグ」「予測」「フラグ付き」といった組み込みパースペクティブが用意されていて、これだけでも普段使いとしては十分に強力です。さらに、Proであれば 自分の運用に合わせたカスタムパースペクティブをいくつでも作れる ので、「今日やる」「今週レビュー」「インボックス整理」など、自分の生活の節目ごとに専用ビューを持てるようになります。

私がパースペクティブに救われている理由

そして、私がOmniFocusのパースペクティブに 特に 救われているのは、私が「仕事とプライベートの切り替え」が壊滅的に苦手 だからです。

私はもともと、

  • 仕事中なのに「あの買い物しないと」「家のあれ片付けないと」が気になってしまう
  • 逆に休みの日にプライベートを楽しみたいのに、仕事のタスクが頭にチラついて落ち着かない

というタイプで、タスクを一箇所にまとめれば便利な反面、全部が常に視界に入る状態だと、脳の切り替えがどんどん下手になっていく という問題に長らく悩まされてきました。

ここで効くのが、パースペクティブによる 「今いらないものを物理的に視界から消す」 という運用です。

  • 仕事モードのパースペクティブ :仕事用のプロジェクト・タグだけを表示。プライベート系のタスクは 完全に非表示
  • プライベートモードのパースペクティブ :プライベート用のプロジェクト・タグだけを表示。仕事のタスクは 完全に非表示

たったこれだけのことなのですが、「見えないものは気にならない」 という人間の性質を利用できるおかげで、思考の切り替えが圧倒的にラクになりました。仕事中に開くOmniFocusには仕事のタスクしかないし、退勤後に開くOmniFocusにはプライベートのタスクしかない。脳が勝手に「今モード」に乗っかってくれるようになります。

「タスクを全部1か所にまとめる」と「今のモードに集中する」は普通だと両立しにくいのですが、パースペクティブはその矛盾を綺麗に解決してくれる ので、私のように切り替えが苦手な人ほど効果を実感できるはずです。

なお、こうしたカスタムパースペクティブ(自分でフィルタ条件を組んで作るもの)は Pro機能 なので、利用するにはPro版もしくはサブスクリプション版が必要です(詳細は後述の価格セクションで)。

iOSショートカットとの相性が抜群

OmniFocusのショートカットアクション一覧
OmniFocusのショートカットアクション一覧
OmniFocusのショートカットアクション一覧
OmniFocusのショートカットアクション一覧

OmniFocusを使う上で、iPhoneユーザーが絶対に活用すべきなのが iOSショートカットとの連携 です。上のスクリーンショットを見てもらうと分かるとおり、OmniFocusは検索・作成・完了・削除・パースペクティブの呼び出しなど、iOSショートカット用のアクションを非常に豊富に用意しています。タスク管理アプリの中でここまでアクションが揃っているものは珍しく、自分の運用に合わせて自由自在にフローを組み立てられます。中でも特に「これがあるからOmniFocusを選ぶ価値がある」と感じているポイントは次の4つです。

1. タスクを検索できる

iOSショートカットから OmniFocus内のタスクを条件指定で検索 できます。タイトル・タグ・プロジェクト・期限・完了状態などを組み合わせてクエリを書けるので、「今日の○○タグの未完了タスク」みたいなピンポイントな抽出がショートカット側で完結します。

2. 検索結果を使って If 分岐が組める

検索結果を iOSショートカットのIfブロックに渡して条件分岐 ができます。検索で取得できるのは基本的に タスクのタイトル(テキスト) ですが、これで十分実用になります。

たとえば、

  • 「『○○』というタイトルのタスクがインボックスに存在するなら、このフローを実行する」
  • 「『インボックス』に未整理のタスク残っているなら通知、無ければスキップ」
  • 「特定タイトルのタスクが見つかったら、それに連動した別ショートカットを起動」

といった具合に、『特定のタスクがあるなら、これをやる』 というフローをショートカット側で組めます。OmniFocusが単なる「タスクの箱」ではなく、自動化フローの判定条件として使えるデータベース に化けるのが、この機能の本当の価値です。

3. Omni Automationスクリプトを実行できる

iOSショートカットから Omni Automationスクリプト(後述)を呼び出して実行 できます。ショートカットだけだと面倒な複雑処理を、OmniFocus内部のJSスクリプトに丸投げできるので、「外側はショートカット、内側はOmni Automation」という役割分担が綺麗にハマります。

4. タスクを完了できる

ショートカットから タスクを完了状態に変更 できます。これがあると、「外部の作業が終わったら、OmniFocus側のタスクも勝手に完了になる」というフローが組めます。ジョブカン打刻のように「タスクを開いて作業 → 作業完了でタスクも自動完了」が一気通貫で繋がるのは、この機能のおかげです。


さらに、タスクのメモ欄にiOSショートカットのURLを書いておけば、タスクをタップした瞬間にショートカットが起動する という芸当も可能です。

私の運用例:

  1. OmniFocusの「ジョブカン打刻」タスクのメモにiOSショートカットのURLを設定
  2. タスクをタップするとショートカットが起動し、Safariでジョブカンのログインページが開く
  3. Tampermonkeyで自動ログイン→打刻
  4. 打刻後、omnifocus:// スキームでOmniFocusに自動的に戻る
  5. タスクは完了扱いになる

「タスクを開く」という1アクションが、「業務を進める」という具体的な操作に直結している感じです。タスク管理アプリにありがちな「タスクをチェックすること自体が仕事になる」状態を、自然に回避できます。

Omni Automationでアプリ内をスクリプト制御できる

iOSショートカットの外側でもうひとつ強力なのが、Omni Automation です。これはOmni Group製アプリ全体で使えるJavaScriptベースの自動化フレームワークで、もちろんOmniFocusでも動きます。

iOSショートカットが「アプリ外からの呼び出し」だとすると、Omni Automationは「アプリ内部のロジック」を書ける仕組みです。iOS版でもMac版とほぼ同じスクリプトが動く のがありがたいところで、私はちょこちょこ書いた小さなスクリプトをプラグインとしてiPhoneに突っ込んで使っています。

実際に使っているスクリプト

汎用的な話だとイメージしにくいので、私が実際にiOS版OmniFocusに突っ込んで日常的に使っているプラグインを3つ紹介します。

私が使っているOmni Automationのスクリプト
私が使っているOmni Automationのスクリプト

1. プロジェクトの統合:選んだ「残す側」に、もう片方のタスクを全部移す

前述のとおり、私は Python製アプリでTaskPaperテキストを生成 → OmniFocusに投入 しています。ただ、こうやって流し込んだプロジェクトと 既存の同種プロジェクトが並んでしまう ことがあるため、それを統合するスクリプトを書きました。

具体的には、既存プロジェクトとTaskPaper由来の新規プロジェクトの2つを選択 → スクリプトを実行 → 「残す側」として選んだ方のプロジェクトはそのまま残し、もう片方のタスクをすべて残す側へ移動して、空になったプロジェクトは削除 します。これで「テキストから生成 → 統合」の流れが手作業ゼロで完結します。

JavaScript
/*{
    "type": "action",
    "targets": ["omnifocus"],
    "author": "Geek-note",
    "identifier": "com.geek-note.omnifocus.mergeProjects",
    "version": "1.0",
    "description": "選択した複数のプロジェクトを一つに結合します。残すプロジェクトを選択し、他のプロジェクトのタスクをすべて移動します。",
    "label": "プロジェクトを結合",
    "shortLabel": "プロジェクト結合",
    "image": "arrow.triangle.merge"
}*/

(() => {
    const action = new PlugIn.Action(async function(selection) {
        const projects = selection.projects;
        const projectNames = projects.map(p => p.name);

        // 残すプロジェクトを選択するフォームを表示
        const form = new Form();
        form.addField(new Form.Field.Option(
            "targetProject",
            "残すプロジェクト",
            projectNames,
            projectNames,
            projectNames[0]
        ));

        try {
            await form.show("プロジェクトを結合", "結合する");
        } catch (err) {
            return; // キャンセル時は何もしない
        }

        const targetName = form.values["targetProject"];
        const targetProject = projects.find(p => p.name === targetName);
        const sourceProjects = projects.filter(p => p !== targetProject);

        let movedCount = 0;

        sourceProjects.forEach(sourceProject => {
            // 直接の子タスクのみ移動(サブタスクは親と一緒に移動される)
            const tasks = sourceProject.tasks.slice();
            if (tasks.length > 0) {
                moveTasks(tasks, targetProject.ending);
                movedCount += tasks.length;
            }
            // 空になったプロジェクトをドロップ
            sourceProject.status = Project.Status.Dropped;
        });

        new Alert(
            "結合完了",
            `${sourceProjects.length} 個のプロジェクトから ${movedCount} 件のタスクを「${targetName}」に移動しました。\n統合元プロジェクトはドロップしました。`
        ).show();
    });

    action.validate = function(selection) {
        // 2つ以上のプロジェクトが選択されている場合のみ有効
        return selection.projects.length >= 2;
    };

    return action;
})();

2. 期限から逆算して通知を一括登録する

OmniFocusのタスクには期限を設定できますが、私は 期限直前にだけ通知が来ても遅い ので、「3日前」「1日前」「当日朝」のように 段階的なリマインドを入れたい タイプです。

これを毎回手で設定するのは現実的でないので、指定したタスク(あるいはタグ・プロジェクトで絞り込んだタスク群)について、期限から逆算した複数の通知をまとめて自動登録するスクリプト を書いて使っています。期限を更新したらスクリプトを叩き直すだけで、通知群が再生成されるようになっています。

JavaScript
/*{
  "type": "action",
  "targets": ["omnifocus"],
  "author": "Geek-note",
  "identifier": "com.geek-note.omnifocus.setFutureDueNotifications",
  "version": "1.0",
  "description": "期限付きの未完了アクション/プロジェクトに対して、未来の期限前通知を一括追加し、1件でも追加できたものには通知設定済タグを付ける。重複を排除し、除外タグがあるものは処理しない。",
  "label": "期限前通知一括設定",
  "shortLabel": "期限前通知一括設定",
  "paletteLabel": "期限前通知一括設定",
  "image": "bell.circle.fill"
}*/

(() => {
  const action = new PlugIn.Action(function(selection, sender) {
    try {
      const now = new Date();

      // 除外タグ名
      const excludeTagNames = ["🔔通知設定済", "🕕Routine"];
      const excludeTags = excludeTagNames.map(name => {
        const tag = flattenedTags.find(t => t.name === name);
        return tag || new Tag(name);
      });
      const notifyTag = excludeTags[0]; // 🔔通知設定済

      // 通知タイミング(秒数)
      const offsetSecondsList = [
        60, 300, 600, 900, 1800,
        3600, 7200, 10800, 21600,
        43200, 86400, 259200, 604800, 1209600
      ];

      // 再帰的にすべてのアクションを取得
      function collectAllTasks(taskArray) {
        const result = [];
        taskArray.forEach(task => {
          result.push(task);
          if (task.tasks && task.tasks.length > 0) {
            result.push(...collectAllTasks(task.tasks));
          }
        });
        return result;
      }

      const topTasks = Array.from(flattenedTasks || []);
      const nestedTasks = collectAllTasks(topTasks);
      const inboxTasks = Array.from(Database.inboxTasks || []);
      const projects = Array.from(Database.projects || []);

      // 全アイテム + UIDで重複排除
      const allItems = [...projects, ...inboxTasks, ...nestedTasks];
      const seen = new Set();
      const uniqueItems = allItems.filter(item => {
        const id = item.id.primaryKey;
        if (seen.has(id)) return false;
        seen.add(id);
        return true;
      });

      let processedCount = 0;

      uniqueItems.forEach(item => {
        if (!item.dueDate || item.completed) return;

        if ((item.tags || []).some(tag => excludeTags.includes(tag))) return;

        const due = item.dueDate;
        let added = 0;

        offsetSecondsList.forEach(offset => {
          const notifyDate = new Date(due.getTime() - offset * 1000);
          if (notifyDate > now) {
            item.addNotification(notifyDate);
            added++;
          }
        });

        if (added > 0) {
          item.addTag(notifyTag);
          processedCount++;
        }
      });

      new Alert("完了", `通知を設定したアイテム数: ${processedCount} 件`).show();

    } catch (err) {
      new Alert("エラー", `${err.name}: ${err.message}`).show();
    }
  });

  action.validate = function(selection, sender) {
    return true;
  };

  return action;
})();

3. 「今日」タグのタスクに、時間をずらして個別通知を登録する

私は「今日やる」と決めたタスクに 「今日」タグ を付ける運用をしています。ただ、何件もあるタスクに全部同じ時間で通知を入れると、結局1回の通知で全部流れてしまって意味がなくなります。

そこで、「今日」タグが付いた未完了タスクを一覧化 → タスクごとに時間をずらして通知を順次登録するスクリプト を作りました。たとえば「9:00、10:00、11:00……」「9:03、10:03、11:03……」のように時間をずらして並べることで、iPhoneが1日かけて「次はこれだよ」と順番に教えてくれる ようになります。「今日タグを付けて、スクリプトを叩く」だけで、その日のスケジューリングが完了する感じです。

JavaScript
/*{
  "type": "action",
  "targets": ["omnifocus"],
  "author": "Geek-note",
  "identifier": "com.example.today-task-notification",
  "version": "2.5",
  "description": "📆今日 タグが付いた未完了タスクに、9〜21時まで毎時通知(+2分ずつ)。期限を当日22:02からずらして設定。",
  "label": "📅今日タスク通知+期限(ずらし)",
  "shortLabel": "今日通知+期限",
  "paletteLabel": "📅今日通知+期限(ずらし)",
  "image": "calendar.badge.clock"
}*/

(() => {
  const action = new PlugIn.Action(function(context) {
    const tagName = "📆今日";
    const startHour = 9;
    const endHour = 21;
    const dueHour = 22;
    const intervalMinutes = 2;

    function todayAt(hour, minuteOffset) {
      const now = new Date();
      return new Date(now.getFullYear(), now.getMonth(), now.getDate(), hour, minuteOffset);
    }

    const allTags = context.database.tags;
    const targetTag = allTags.find(tag => tag.name === tagName);

    if (!targetTag) {
      new Alert("エラー", `タグ「${tagName}」が見つかりません`).show();
      return;
    }

    const taggedTasks = targetTag.tasks.filter(task => !task.completed);
    if (taggedTasks.length === 0) {
      new Alert("通知なし", `タグ「${tagName}」が付いた未完了タスクは見つかりませんでした`).show();
      return;
    }

    taggedTasks.forEach((task, index) => {
      const offset = (index + 1) * intervalMinutes;

      // 通知削除
      (task.notifications || []).forEach(n => task.removeNotification(n));

      // 通知追加(毎時、ずらしあり)
      for (let hour = startHour; hour = endHour; hour++) {
        const notifyTime = todayAt(hour, offset);
        task.addNotification(notifyTime);
      }

      // 期限追加(22時+ずらし)
      const dueDate = todayAt(dueHour, offset);
      task.dueDate = dueDate;
    });

    new Alert("完了", `${taggedTasks.length} 件のタスクに通知と期限を追加しました`).show();
  });

  action.validate = function(context) {
    return true;
  };

  return action;
})();

iOSショートカットだけだと、どうしても「個々のタスクを操作する」レベルで止まりがちですが、Omni Automationを使うと 「データベース全体に対する一括処理」 が書けるので、上で挙げたような「自分の運用ルール」をそのままコードに落とし込めます。運用が進化するにつれて手放せなくなってくる機能です。

メールドロップで外部システムからタスクを投げ込む

もうひとつ便利なのが、メールドロップ(Mail Drop) という機能です。OmniFocusには専用のメールアドレスが発行されていて、そこに送信したメールは自動的にタスクとして取り込まれます。Macを持たず、WindowsからOmniFocusへタスクを追加したい場合には、最も重要な機能だと言えます。

また、メールドロップは自動化ツールとの親和性が高く、連携を一気にシンプルにしてくれます。私の場合、複数の経路からこのメールドロップ宛にタスクを流し込んでいます。

1. ChangeDetectionでウェブサイトの更新を監視する

ChangeDetectionのスクリーンショット
ChangeDetectionのスクリーンショット
ChangeDetectionに登録したサイトに更新が入るとOmniFocusへタスクインされる
ChangeDetectionに登録したサイトに更新が入るとOmniFocusへタスクインされる

普段のウェブサイト更新監視には、OSSの ChangeDetection.io をセルフホストして使っています(自宅サーバー側でどんなサービスを動かしているかは 自宅で動かしているセルフホストサービスと自動化の仕組みを全部棚卸ししてみたよ!というお話 にまとめています)。指定したページの差分が出ると通知を投げてくれるツールなのですが、その通知先として メールドロップのアドレス を指定しています。

自宅で動かしているセルフホストサービスと自動化の仕組みを全部棚卸ししてみたよ!というお話

これで、

  • 監視対象のサイトが更新される
  • ChangeDetectionが差分を検知
  • メールドロップ宛にメール送信
  • OmniFocusのインボックスにタスクとして出現

という流れが完全自動で回ります。「気になるサイトの更新は、OmniFocusのインボックスを見れば全部分かる」状態になります。

2. WindowsからはFlow Launcherでサクッとタスクイン

Flow LauncherからOmniFocusのメールドロップ宛にタスクを送信する様子
Flow LauncherからOmniFocusのメールドロップ宛にタスクを送信する様子

メインPCがWindowsの私にとって、「PCで作業中に思いついたタスクをOmniFocusに入れる手段」も重要です。これは Flow Launcher(Windows用のキーランチャー)と組み合わせて解決しています。

具体的には、

  • Flow Launcherに「OmniFocusにタスクを送る」専用コマンドを登録
  • 内部でメールドロップ宛にメールを送信するスクリプトを叩く
  • 入力した内容がそのままOmniFocusのインボックスに飛ぶ

という仕組みです。Alt + Space でFlow Launcherを呼び出して、コマンドの後ろにタスク名を書いてEnterを押すだけ。iPhoneを取り出すよりも早く、PCの作業を中断せずにタスク登録できる ので、Windows使いとしては手放せない経路になっています。

実際にFlow Launcherから呼び出しているスクリプトはこんな感じです。Apprise(さまざまな通知先にまとめて対応できるPython製の通知ライブラリ)を使って、Gmailの送信サーバー経由でメールドロップ宛にメールを送るだけのシンプルな作りです。

Python
import sys
import apprise

# 引数をすべて1つの文字列にまとめる
query = ' '.join(sys.argv[1:])

# '/' で区切ってタイトルと本文に分ける
if '/' in query:
    title, body = map(str.strip, query.split('/', 1))
else:
    title = query
    body = " "  # 本文がない場合は空白を入れる

# Apprise 通知設定
url = "mailtos://smtp.gmail.com:587?user=your_email@gmail.com&pass=your_app_password&from=your_email@gmail.com&to=your_omnifocus_maildrop@sync.omnigroup.com"

a = apprise.Apprise()
a.add(url)

a.notify(
    title=title,
    body=body
)

Flow Launcher側でコマンドに続けて入力した文字列をsys.argvで受け取り、/があれば「タイトル / 本文」として分割、無ければ全体をタイトル扱いにしています。あとはApprise の mailtos:// スキームでGmailのSMTPサーバーからメールドロップのアドレス(to=)宛にメール送信するだけです。userpassfromto には自分のGmailアドレスとアプリパスワード、OmniFocusのメールドロップアドレスをそれぞれ入れる形になります。


メールドロップが優秀なのは、「メールを送れるシステムなら何でも連携できる」というシンプルさです。ChangeDetection、Flow Launcher、Zapier、各種SaaSの通知……どれでもOK。Webhookやpush通知と違って、「通知に気づかず流れていく」ことがありません。気になる情報は全部OmniFocusのインボックスに集約される ので、後で必ず目に入ります。

Windowsメインの自分にとって、メールドロップは 「PC側で発生した情報をOmniFocusに流し込む」唯一にして最強の経路 になっています。

TaskPaper形式で「テキストでタスクを書く」

地味に効いてくるのが、TaskPaper形式 に対応している点です。TaskPaperは元々別の同名アプリで使われている、プレーンテキストでタスクツリーを書くための記法で、OmniFocusはこれを インポート・エクスポート両方 で扱えます。

書き方はざっくりこんな感じ:

TaskPaper
朝のルーティン:
    - ジョブカン打刻 @parallel(false) @autodone(true)
        - Safariを開く
        - 打刻ボタンを押す
    - メールチェック @due(2026-06-11 09:00)
    - 今日のタスクを確認 @tags(daily)

これだけで、プロジェクトとサブタスク、タグ、期限まで一気に表現できます。OmniFocusはこのテキストをそのままタスクツリーに変換してくれます。

ただし注意点として、メールドロップ経由でTaskPaper形式のテキストを送ってもタスクツリーには展開されません(メールドロップはあくまで単一タスクの取り込み窓口で、本文はメモ欄に入る扱いになります)。TaskPaperを活かすには、omnifocus:// の専用URLスキームに渡す か、iOSショートカットのアクションでTaskPaperテキストを投入する ルートを使う必要があります。

私の場合は、Python製の自作アプリでTaskPaperテキストを生成 しています。Windows側で動かしているこのアプリが、定型プロジェクトのテンプレートや、外部データから組み立てたタスクツリーをTaskPaper形式で吐き出してくれて、それをOmniFocusに流し込む、という運用です。

  • 定型プロジェクトのひな形をPython側でテンプレ化
  • 外部データ(CSV・スプレッドシート・スクレイピング結果など)から動的にタスクツリーを生成
  • 生成したTaskPaperテキストをOmniFocusに投入

「テキストでプロジェクト設計→OmniFocusで実行」というフローが取れるのが本当に強くて、複雑なプロジェクトの初期投入が圧倒的に楽になります。Windowsメインの自分にとって、Python + TaskPaperの組み合わせは「PC側からまとまった構造のタスクを投入する唯一の現実解」 になっています。

実例:バイクの給油タイミングをOmniFocusに任せている話

ここまでの仕組みを組み合わせると、こんな「ちょっと未来っぽい」運用ができるようになります。私が実際にやっているバイク通勤での例を紹介します。

私はバイク通勤しているのですが、その走行距離管理〜給油タイミング通知までを、OmniFocusを中心に組んでいます。

1. B+COM(バイク用インカム)の起動・停止をトリガーに使う

iPhoneがB+COMとBluetooth接続される/切断されるタイミングを、iOSショートカットのオートメーションで拾います。これで「乗車開始」「降車」が自動検知できます。接続時には、走行中に不要な通信を発生させないようWi-FiとVPN(Tailscale)のオンデマンド接続もまとめてオフにしつつ、「走行開始」「ガソリン給油通知」「ジョブカン打刻確認」の3つのショートカットを連続実行しています。

B+COMに接続されたときのオートメーション
B+COMに接続されたときのオートメーション。Wi-FiとVPNのオンデマンド接続をオフにしつつ、「走行開始」「ガソリン給油通知」「ジョブカン打刻確認」の各ショートカットを順に実行する

逆に接続が切れたとき(=バイクを降りたとき)は、「走行終了」ショートカットを実行したあとWi-FiとVPNのオンデマンド接続を元の状態に戻します。

B+COMとの接続が解除されたときのオートメーション
B+COMとの接続が解除されたときのオートメーション。「走行終了」ショートカットを実行したあと、Wi-FiとVPNのオンデマンド接続を元に戻す

2. Data Jarで走行距離を記録

乗車開始/降車のタイミングで、ショートカットから Data Jar に走行距離(区間値・累計値)を書き込みます。Data JarはiOSショートカットから読み書きできる軽量な永続アプリで、こういう「数値を貯めておく」用途にちょうど良いです。具体的には、「走行開始」ショートカットで乗車地点と時刻を記録しつつ累計距離をチェックし、「走行終了」ショートカットでGPSベースと経過時間ベースの2通りの計算結果を平均して走行距離を確定、累計値に加算しています。

「走行開始」ショートカット
「走行開始」ショートカット
「走行開始」ショートカット:現在地と現在時刻をData Jarのstart_placestart_timeに保存し、累計距離total_distanceが100kmを超えていたらOmniFocusで「バイクのガソリンを給油する」タスクの有無を検索し、無ければ新規追加する(次項の給油タスク投入は、ここで行っています)
「走行終了」ショートカット
「走行終了」ショートカット
「走行終了」ショートカット:start_timeからの経過時間が4分未満なら誤検知とみなしてスキップし、それ以外はGPS距離と経過時間ベースの距離を平均して今回の走行距離を確定、累計値total_distanceとログlog_distanceを更新する

3. 累計距離が一定値を超えたら、OmniFocusに「給油」タスクを投入

累計値が閾値を超えたら、ショートカットから OmniFocusに「給油」タスクを作成 します。これでOmniFocus側に「給油すべき状態である」というフラグが立った状態になります。この判定は前項の「走行開始」ショートカットの中で毎回行われており、total_distanceが閾値(100km)を超えていたらOmniFocusで給油タスクの有無を検索し、まだ無ければ新規作成する、という流れです。

4. ガソリンスタンドが近づいたら、給油タスクの有無で判定

位置情報ベースのオートメーションで「ガソリンスタンドに近づいた」イベントを拾い、ショートカットから OmniFocusを検索します。「給油」タスクが存在するなら音声で通知 を流す、というフローです。具体的には、「自分がENEOS〇〇SSに到着したとき」を条件にオートメーションを組み、そこから「ガソリン給油通知」ショートカットを呼び出しています。ショートカット側では、OmniFocusでタイトルに「ガソリン」を含み・状態が「残り」であるアクションを検索し、該当タスクが見つかった場合だけbikeフォルダに用意しておいたサウンドファイルを再生して知らせる、という作りです。

「ガソリン給油通知」ショートカット
「ENEOS〇〇SSに到着したとき」のオートメーションから「ガソリン給油通知」ショートカットを実行。OmniFocusで「ガソリン」を含み残りの状態のタスクを検索し、見つかった場合のみbikeフォルダ内のサウンドファイルを再生する

5. 「支払方法」ショートカットに「給油タスク完了 + 累計距離リセット」を仕込む

給油時はエネオスアプリで支払いをするのですが、普段いろいろな決済手段(PayPay・楽天ペイ・各種ポイントカードなど)をメニューから選ぶ「支払方法」という汎用ショートカットを使っており、その選択肢の一つに 「ガソリン給油」 という項目を追加しています。これを選ぶと、

  • 「走行距離をリセットしますか?」の確認アラートを出したうえで、Data Jarのtotal_distance(累計走行距離)を0にリセット
  • 現在地・現在時刻をstart_placestart_timeとして保存し直す(次の走行開始地点の基準にする)
  • ENEOS公式アプリを開く
  • OmniFocusで「バイクのガソリンを給油する」タスク(状態:残り)を検索し、見つかればそのタスクを完了にする

という処理を仕込んでいます。

「支払方法」ショートカットの「ガソリン給油」
「支払方法」ショートカットの選択肢に「ガソリン給油」を追加。選択すると走行距離リセットの確認→total_distanceを0に→現在地・現在時刻をstart_placestart_timeに保存→ENEOS公式アプリを開く、という流れが走る
OmniFocusの給油タスクを完了にする処理
続けてOmniFocusで「バイクのガソリンを給油する」タスク(状態:残り)を検索し、見つかった場合はそのタスクをComplete(完了)にする

つまり、支払いのためにアプリを開く=給油タスクの完了+距離リセットが同時に走る という構造です。「給油したらタスクを完了するのを忘れる」みたいなヒューマンエラーが起きる余地が無くなって、次のサイクルがそのまま自動で始まります。

このフローのポイントは、OmniFocusが「今、給油すべき状態かどうか」を保持してくれている という点です。位置情報トリガーは常に走っていますが、給油タスクが無いときは何もしません。OmniFocusが状態フラグの代わりとして機能している わけです。

ここまでくると、OmniFocusはもはやタスク管理アプリというより、「自分の生活の状態」を保持して必要なときに音声で囁いてくれる相棒 に近い存在になっていきます。これが組めるのは、

  • iOSショートカットからOmniFocusを 検索 → If判定 できる
  • 検索結果に応じて任意のアクション(音声通知など)を組める
  • B+COMやガソリンスタンドのような 外部イベントをトリガーに使える

という、これまで紹介してきた要素がすべて噛み合っているからです。

正直に言うと、めちゃくちゃ高い

ここまで散々褒めてきましたが、OmniFocusには どうしても無視できない欠点 があります。それは 値段 です。

おそらく タスク管理アプリの中で最も高価な部類 で、サブスクリプション版・買い切り版どちらを選んでも、他のタスク管理アプリと比較すると頭一つ抜けた価格帯になっています。記事執筆時点の公式ストア価格は以下のとおりです。買い切り版とサブスクリプション版は iPhoneのApp Store経由で円建て購入、Web版単体は 公式サイトからのUSD決済のみ という構成になっています。

購入形態価格購入経路含まれるもの
サブスクリプション(月額)1,050円 / 月App StoreMac・iPhone・iPad・Apple Watch・Vision Pro + Web版
サブスクリプション(年額)10,400円 / 年App Store同上
買い切り Standard12,000円(買い切り)App Store全Appleプラットフォーム(Web版は含まれない)
買い切り Pro25,000円(買い切り)App StoreStandard + Pro機能(カスタムパースペクティブ・Omni Automation など)
Web版のみ(月額)$4.99 / 月公式サイト(USD)OmniFocus for the Webのみ
Web版のみ(年額)$49.99 / 年公式サイト(USD)同上

買い切り版でも Pro(フル機能版)は25,000円 という、買い切りタスク管理アプリとしては破格の値段です。サブスクリプション版も 年額10,400円 で、Todoistのような競合と並べると、ぶっちゃけギョッとするレベル。さらに、カスタムパースペクティブやOmni Automationなどの “Pro機能” は上位プランでしか使えない ので、本記事で紹介した自動化を全力で使いこなしたいなら、必然的にProを選ぶことになります。

ちなみに 買い切り版はiPhone単体のApp Store内課金(In-App Purchase)からそのまま購入できます。私のように Macを持っていないWindowsユーザーでも、iPhoneのApp Storeを開いて「Unlock Standard 12,000円」「Unlock Pro 25,000円」をタップすれば購入完了 です。「OmniFocusってMacが無いと買えないんじゃないの?」と思っていた人は安心してください。

ただし、買い切りライセンスは ユニバーサルライセンス(同じライセンスでMac・iPad・Apple Watch・Vision Proでも使える) なので、iPhoneだけで使うつもりでも値段は変わりません。「iOS版だから安く買える」みたいな抜け道は無くて、Mac版とまったく同じ価格(Standard 12,000円 / Pro 25,000円)を払うことになります。

「タスク管理にそんなにお金かけるの?」と聞かれたら、正直返す言葉に詰まる金額です。それでも私は払い続けていて、その理由は、

  • 自動化のハブとしての投資対効果が圧倒的に高い
  • 一度組んだワークフローが何年も使える
  • 「タスク管理アプリ難民」を卒業できる安心感

このあたりに集約されます。価格に納得できるかどうかが、OmniFocus導入の最大の関門 だと思っています。逆に言えば、ここさえクリアできれば、長く付き合える相棒になってくれるはずです。なお、初めての人は 2週間の無料トライアル で全機能を試せるので、まずはそこから入るのがおすすめです。

OmniFocusを「通知ハブ」にして得たもの

こうして使い込んでいくと、OmniFocusは単なるタスク管理アプリではなく、自分の認知の一部を肩代わりしてくれる外部メモリ のような存在になっていきます。

  • 覚えておくべきことは全部OmniFocusに入れる
  • 自動化システムからの通知もメールドロップでOmniFocusに集約する
  • iOSショートカット・Omni Automationで「タスクから作業へ」を一気通貫
  • TaskPaperで複雑なプロジェクトもテキストから一発投入

結果として、頭の中は常にすっきり、目の前の作業に集中できる時間が増えました。

まとめ

OmniFocusはGTDという確立された方法論を土台にしながら、パースペクティブによる「見せる/見せない」の切り替え、iOSショートカットとOmni Automationによる自動化、メールドロップという外部からの受け口、TaskPaperによるテキストからの一括投入まで、単なるタスク管理アプリの枠をとっくに超えたアプリだと感じています。バイクの給油タイミングの例のように、自分の生活の”状態”を静かに保持しておいて、必要なときだけ声をかけてくれる相棒になれるツールは、他になかなか思い当たりません。しかもそれが、Macを持たずiPhoneだけの運用でも十分に成立してしまうというのが、Windowsメインの自分にとっては何よりの魅力でした。

もちろん、タスク管理アプリの中ではおそらく最も高価な部類に入り、価格を見た瞬間に腰が引ける気持ちもよく分かります。それでも、一度組んだ自動化のフローは何年経っても静かに働き続けてくれますし、あちこちのタスク管理アプリを渡り歩く「難民生活」から卒業できた安心感も含めて考えれば、十分に元が取れる投資だったと今でも思っています。

タスク管理アプリ選びで迷っている方、特に iPhoneユーザーで、自動化や仕組み化が好きな方 には、ぜひ一度試してほしいアプリです。私のように メインPCがWindowsでも、iOS版だけで全然戦えます。価格は最初に見ると確実に怯みますが、自動化のハブとして長く使い倒すなら、十分元が取れるアプリだと個人的には感じています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です