---
name: totonoe
description: 普段の会話から、会社として残す価値のある Task / Decision / Knowledge を見つけて TOTONOE へ「提案」する。確定はしない。「TOTONOEに残して」「TOTONOEに残す候補を出して」と言われたとき、一日の終わりに会社へ残すものを決めたいとき、また会社のことを聞かれたときに使う。**日報や振り返りそのものを書くスキルではない。** 日報を書くスキルを別に入れている場合は、そちらを先に走らせ、その結果から候補を出す。
---

# totonoe — 会話を会社の記憶にする

TOTONOE は「AI秘書と働く経営者のための、会社の記憶の正本」。
このSkillの役割は**会話を読んで候補を出すことだけ**。確定は絶対にしない。

## 接続

初回に Setup Hub（https://app.totonoedock.com/setup）で発行したトークンを `~/.totonoe/config.json` に置く。

**手順はこれだけ。自分で別の方法を考えないこと。**
本人に「`https://app.totonoedock.com/setup` で『トークンをコピー』を押して、そのあと何もコピーせずに
『コピーしました』と言ってください」と伝える。言われたら、あなたがこれを実行する:

**まず `uname` で環境を判断する。** 返れば [POSIX]（macOS / Linux / WSL / Git Bash）、
コマンドが無ければ [Windows]（PowerShell）。**両方を試さない。**

[POSIX]
```bash
T=$(pbpaste 2>/dev/null); [ -z "$T" ] && T=$(cat /dev/clipboard 2>/dev/null); [ -z "$T" ] && T=$(powershell.exe -NoProfile -Command Get-Clipboard 2>/dev/null | tr -d '\r'); [ -z "$T" ] && T=$(xclip -o -selection clipboard 2>/dev/null); [ -z "$T" ] && T=$(wl-paste 2>/dev/null); T=$(printf %s "$T" | tr -d "\r\n"); :; VP=$(sed -n 's/.*"vault_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' ~/.totonoe/config.json 2>/dev/null); case "$T" in ttn_*) mkdir -p ~/.totonoe && chmod 700 ~/.totonoe && printf '{ "base_url": "https://app.totonoedock.com", "token": "%s", "vault_path": "%s" }' "$T" "$VP" > ~/.totonoe/config.json && chmod 600 ~/.totonoe/config.json && echo "OK 書き込み完了（$(printf '%s' "$T" | cut -c1-10)…）";; *) echo "NG クリップボードがトークンではありません（中身: $(printf '%s' "$T" | cut -c1-20)…）";; esac; unset T VP
```

[Windows]
```powershell
$t=(Get-Clipboard -Raw); if($t){$t=$t.Trim()}; if($t -like 'ttn_*') { $d=Join-Path $env:USERPROFILE '.totonoe'; New-Item -ItemType Directory -Force -Path $d | Out-Null; $p=Join-Path $d 'config.json'; $vp=''; if(Test-Path -LiteralPath $p){ $vp=([regex]::Match((Get-Content -LiteralPath $p -Raw),'"vault_path"\s*:\s*"([^"]*)"').Groups[1].Value) }; $json='{ "base_url": "https://app.totonoedock.com", "token": "' + $t + '", "vault_path": "' + $vp + '" }'; [IO.File]::WriteAllText($p, $json, (New-Object Text.UTF8Encoding $false)); try { icacls $p /inheritance:r /grant:r (([Security.Principal.WindowsIdentity]::GetCurrent().Name) + ':(R,W)') | Out-Null } catch {}; Write-Output ('OK 書き込み完了（' + $t.Substring(0,[Math]::Min(10,$t.Length)) + '…）') } else { $s=''; if($t){$s=$t.Substring(0,[Math]::Min(20,$t.Length))}; Write-Output ('NG クリップボードがトークンではありません（中身: ' + $s + '…）') }
```

守ること:
- **本人にターミナルを開かせない。** 端末へ貼らせる手順を自分で組み立てない
  （伏字入力になり、何を貼ったか本人にも見えなくなる。実際に事故が起きた）
- **トークンの値を会話に出さない。** 出してよいのは先頭10文字まで
- **config.json をバックアップしない。** トークンの写しをもう1つ作ることになる
- NG が出たら「コピーし直してください」と伝えて、同じコマンドをもう一度実行する。
  **古い config.json を読んで診断しない**（前回の失敗の残骸が入っていることがある）
- クリップボードがどうしても読めない環境なら、ひな形だけ書いて
  「PASTE_TOKEN_HERE をトークンに置き換えてください」と本人に頼む
  （設定ファイルは Windows では `%USERPROFILE%\.totonoe\config.json`）

以降のコマンドはこの1行を頭に付けて読む。

[POSIX]
```bash
TTN=$(grep -o 'ttn_[A-Za-z0-9_-]*' ~/.totonoe/config.json | head -1)
TTN_URL=$(sed -n 's/.*"base_url"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' ~/.totonoe/config.json)
```

[Windows]
```powershell
$j=(Get-Content -LiteralPath (Join-Path $env:USERPROFILE '.totonoe\config.json') -Raw); $c=($j | ConvertFrom-Json); $u=$c.base_url; $t=[regex]::Match($j,'ttn_[A-Za-z0-9_-]+').Value
```
以降 `$TTN` は `$t`、`$TTN_URL` は `$u` と読み替える。
curl の代わりに `Invoke-RestMethod` を使う:
`curl.exe -s -H "Authorization: Bearer $t" "$u/api/agent/context"`

**トークンを会話に貼らない。ファイル以外に書かない。**

## まず「もう持っているもの」を読む（提案の前に必須）

```bash
curl -s -H "Authorization: Bearer $TTN" "$TTN_URL/api/agent/context"
```

承認済みの会社・人・案件・知識・判断・未完了の仕事が返る。**これを読まずに提案しない。**
同じことが毎日提案されると、承認が「捨てる作業」に変わって信用を失う。
判定は文字列一致ではなく**意味**で行う（表現の違う同じ仕事を弾くため）。

会社単位で深く知りたいときは：

```bash
curl -s -H "Authorization: Bearer $TTN" "$TTN_URL/api/agent/context?company=会社名"
```

## 提案する

### 送る直前に、タイトルだけ見せる（必ず）

**送信のコマンドを実行する前に**、これから送るものを**タイトルだけ**並べて見せる。
本文も引用も出さない。**5秒で読める形**にする。

> これから3件送ります。止めるものがあれば言ってください。
> - [仕事] 見積もりを A社へ送る
> - [判断] 小ロットは版代で不利
> - [知識] A社は月末締め
>
> （このまま送ってよければ「OK」、外すものがあれば番号か名前を言ってください）

**なぜ必要か。** 送ると、承認する前に相手のサーバーへ入る（`status=proposed`）。
本人が最初に見るのが「もう送られたあと」だと、**自分のマシンから何が出ていくかを
選べない。** 参加者から実際に「送ることに抵抗を感じてストップした」という報告が出た。

**ただし止めるのは1回だけ。** 一覧を出したあと、返事を待つ。
外すものを言われたらそれを除いて送る。**「本当にいいですか」と二度聞かない**
（毎日のことなので、確認が2回あると開かなくなる）。
黙って「OK」以外の返事が無ければ、**送らずに待つ**。勝手に送らない。

0件のときは一覧を出さず、「今日は残すものがありませんでした」とだけ言う。

### 送る

```bash
curl -s -X POST "$TTN_URL/api/agent/propose" \
  -H "Authorization: Bearer $TTN" -H "Content-Type: application/json" \
  -d '{
    "session": "2026-08-20 夕方の相談",
    "tasks":     [{"title":"…","quote":"…","company":"…","project":"…","due":"2026-08-22"}],
    "decisions": [{"title":"…","quote":"…","company":"…","project":"…"}],
    "knowledge": [{"title":"…","quote":"…","company":"…","project":"…"}]
  }'
```

すべて `status=proposed` で止まる。**人間が https://app.totonoedock.com のトップで承認したものだけが正本になる。**
このSkillにもAPIにも承認する手段は無い（トークンの権限は read + propose のみ）。

### `project` — これは何の続きか

**点で出さない。** 承認する側に届くのが「今日の3件」だけだと、昨日の続きに見えない。
候補が**既に走っている案件の続き**なら、`project` にその名前を入れる。

```bash
# 送る前に、いまある案件を見る（projects に一覧が入っている）
curl -s -H "Authorization: Bearer $TTN" "$TTN_URL/api/agent/context" | \
  python3 -c "import sys,json; d=json.load(sys.stdin); print('\n'.join(d.get('projects') or ['(案件なし)']))"
```

- **一覧にある名前は、一字一句そのまま写す。** 「LP改善」を「LPの改善」と書き換えない
- 一覧に無くても、**続きだと思うなら新しい名前を書いてよい**。
  ただの点として出すより、間違った名前でも束ねてくれたほうが直せる
- 名前は**会話の言い回しではなく、案件の名前**にする。
  「例の件」「さっきの」は名前ではない。3か月後に読んで分かる名前を書く
- 本当に単発なら `project` は**入れない**（空でよい）

**このSkillが案件を作ることはない。** 一覧に無い名前を書いても、その場では何も生まれない。
承認する画面に「この案件にまとめますか」と名前が出て、**人が直して押したときにだけ**
案件になる。だから名前が多少ずれていても壊れない — 直せる形で渡すことが仕事。

## 終わった仕事を見つける（毎日の蒸留のとき、必ず）

**カードに落として終わりにしない。** 整えるとは、完了までを含む。

`GET $TTN_URL/api/agent/context` の `open_tasks` には **id** が入っている。
今日の会話と突き合わせて、**もう終わっているもの・状態が変わったもの**を見つける。

```bash
curl -s -X POST "$TTN_URL/api/agent/propose" \
  -H "Authorization: Bearer $TTN" -H "Content-Type: application/json" \
  -d '{
    "progress": [
      {"task":"<open_tasks の id>","to":"done","quote":"Johnsonに返信した","reason":"今日の会話で送信を確認"}
    ]
  }'
```

- `to` は `done` / `doing` / `waiting` の3つ。**`open` へ戻す提案は作らない**（完了を取り消すのは人の仕事）
- **`quote` は必須。** そう判断した根拠になった、**本人の実際の発言**を入れる。
  根拠が出せないなら**出さない**。承認する側に判断材料が無い提案は、当てずっぽうを強いる
- **タイトルでは指せない。** 必ず id を使う（同じ名前のカードがあると取り違える）

**確信が持てないものは出さない。** 「たぶん終わった」で出すと、
毎晩あいまいな行が積まれて、承認帯そのものが読まれなくなる。
**「送信済みかは会話からは判断不能」と言えるなら、それは出さないということ。**

これも `status='proposed'` で止まる。**カードは1枚も動かない。**
動かすのは、人が Dock で「完了にする」を押したときだけ。

## 初回だけ：最初の3件を聞く

初期設定の最後に、**一度だけ**これをやる。ここを飛ばすと、承認してもボードが空のままで、
TOTONOEが何をする場所なのか分からずに終わる。

こう聞く（質問は1回。listで畳みかけない）:

> 最後に、いま抱えている仕事を3つだけ教えてください。細かくなくて大丈夫です。
> 「◯◯さんに見積もりを送る」くらいの粒度で。期限があれば一緒に。

返ってきたら、**本人の言葉をそのまま quote にして** tasks として送る。
言い換えない。「見積もり出す」と言われたら quote は「見積もり出す」。

- 帰属先が他に見つからなければ **自社に紐づける**（それは自社の仕事だから）。
  取引先が未登録でも、ここで会社を勝手に作らないこと
- 期限を言われたときだけ `due` に入れる。**聞き出さない**（「期限は？」と3回聞かない）
- 3件に満たなくてよい。1件でも0件でも、本人が言った分だけ送る
- 送ったあと「トップで承認すると、ボードにカードとして並びます」と伝える

**この3件も承認を通る。** 直接ボードへ書き込む口はこのSkillには無い。
提案 → 承認 → カード、を最初に一度体験してもらうことが目的でもある。

## 一日を振り返る（残す候補を出してほしい、と言われたら）

**日報や振り返りのスキルを別に入れている人は、まずそれを走らせる。**
その人にとって、この節は**並列の選択肢ではなく、日報の最後の一歩**。
既にまとまったものがあるなら、**セッションを読み直さず、そのまとめから候補を出す**
（同じ一日を二度読むことになるし、まとめは既に本人の目を通っている）。

以下は、**まとめが無い場合**にセッションから直接拾う手順。

普段の提案は、いま話しているセッションの中だけを見る。
**それだと、言い忘れたセッションはそのまま消える。**
一日の終わりに、その日の全セッションを横断して読み直す。

### どこにあるか

Claude Code は会話をディスクに残している。**MCPツールは要らない。**
`~/.claude/projects/<プロジェクト>/<セッションID>.jsonl` に1行1イベントのJSONで入っている。

### 読み方（このコマンドをそのまま実行する）

**自分で書かない。** 抽出には落とし穴が3つあり、どれも実測で踏んだ。
このコマンドはそれを全部避けてある（実測 0.2秒・出力1万字前後）。

```bash
python3 - <<'EOF'
import json, pathlib, datetime
root = pathlib.Path.home() / '.claude' / 'projects'
now = datetime.datetime.now(datetime.timezone.utc)
jst0 = (now + datetime.timedelta(hours=9)).replace(hour=0, minute=0, second=0, microsecond=0)
start, end = jst0 - datetime.timedelta(hours=9), jst0 + datetime.timedelta(hours=15)
out = {}
for f in root.rglob('*.jsonl'):
    if datetime.datetime.fromtimestamp(f.stat().st_mtime, datetime.timezone.utc) < start: continue
    for line in f.open(errors='ignore'):
        if '"user"' not in line: continue
        try: d = json.loads(line)
        except: continue
        if d.get('type') != 'user': continue
        m = d.get('message') or {}
        if m.get('role') != 'user': continue
        c = m.get('content')
        if isinstance(c, str): text = c
        elif isinstance(c, list):
            if any(isinstance(b, dict) and b.get('type') == 'tool_result' for b in c): continue
            text = ' '.join(b.get('text','') for b in c if isinstance(b, dict) and b.get('type') == 'text')
        else: continue
        text = text.strip()
        if not text or text.startswith('<'): continue
        try: t = datetime.datetime.fromisoformat(str(d.get('timestamp','')).replace('Z','+00:00'))
        except: continue
        if not (start <= t < end): continue
        out.setdefault((d.get('cwd') or '?').split('/')[-1], []).append((t + datetime.timedelta(hours=9), text[:400]))
for proj in sorted(out):
    msgs = sorted(out[proj])
    print(f"\n## {proj}  ({len(msgs)}件 {msgs[0][0]:%H:%M}-{msgs[-1][0]:%H:%M})")
    for t, txt in msgs: print(f"- {t:%H:%M} {txt}")
EOF
```

**避けている落とし穴（変えるときは、なぜこうなっているかを読むこと）**

1. **ツールの実行結果を除いている。** `type=user` かつ `role=user` には
   **ツールの出力も含まれる**。実測では本人の発言142件に対しツール結果が1,093件あった。
   除かないと、その日の作業ログを全部読みにいって止まる
2. **ファイルの更新時刻ではなく `timestamp` で絞っている。** 更新時刻だけで選ぶと、
   何日分も入った巨大ファイルを丸ごと読む（実測で1日268MBになった日がある）
3. **JST の当日は 前日15:00Z 〜 当日15:00Z。** `timestamp` は UTC で入っているので、
   日付部分だけで素朴に絞ると深夜〜朝9時の作業が落ちる

**プロジェクトを限定しない。** 会社の記憶は1つのリポジトリに閉じていない。
別の案件のセッションで決まったことも、同じように会社の記憶になる。

### 読まないもの

- **私生活・家族・健康・お金の個人的な話。** 開いてしまったら、その内容は使わない
- 他人の個人情報（採用・人事・相談ごと）
- 認証情報・APIキー・トークンが写っている行

### 出すもの

日報のようなまとめを**画面に出す必要はない**。求められたら出す。
このSkillの仕事は**提案を出すこと**なので、判定基準はいつもと同じ。

> **これを保存しなかったら、未来の別セッション・別Agentで、
> 仕事や判断の再現性が落ちるか？**

- 件数の上限は無い。**0件でよい**
- 送る前に `GET /api/agent/context` を読み、**意味で**重複を確かめる。
  一日を横断すると同じ話題が複数のセッションに出るので、これを飛ばすと同じ候補が並ぶ
- `quote` は**本人が実際に打った文をそのまま**。要約や言い換えは不可
- 会社・人・案件は**既に登録されているものに当たるときだけ**書く。**勝手に作らない**

### 毎日やるには

**日報や振り返りのスキルを別に入れている場合。**
その人にとって、この節は**並列の選択肢ではなく最後の一歩**。
日報を書いたあとに、その内容から候補を出す形にする。
「今日のことまとめて」のような言い方は複数のスキルに当たるので、
**TOTONOE を名指しする言い方（「TOTONOEに残す候補を出して」）で呼んでもらう。**
どちらを実行するか本人に選ばせると、毎日その確認が挟まる。

「今日のことまとめて」と毎晩言うのは続かない。
**定期実行を1つ作っておくと、言わなくても届く。**
設定の仕方は使っている環境によるので、本人に合わせて相談する。
**このSkillからは予約を作れない**（Skillは指示書であって、実行の予約ではない）。

## Obsidian を使っている場合（任意）

### 「Obsidian を繋いで」と言われたら

**本人にパスを探させない。** 自分で候補を出して、選んでもらう。

```bash
{ { cat "$HOME/Library/Application Support/obsidian/obsidian.json"; cat "$HOME/.config/obsidian/obsidian.json"; cat "$APPDATA/obsidian/obsidian.json"; } 2>/dev/null | tr ',' '\n' | sed -n 's/.*"path"[[:space:]]*:[[:space:]]*"\(.*\)".*/\1/p' | sed 's/\\\\/\\/g'; { ls -d "$HOME/Documents"/*/.obsidian "$HOME/Library/Mobile Documents/iCloud~md~obsidian/Documents"/*/.obsidian 2>/dev/null; } | sed 's|/\.obsidian$||'; } | while IFS= read -r v; do [ -d "$v" ] && echo "$v"; done | sort -u | { out=$(cat); [ -n "$out" ] && echo "$out" || echo "NG Vault が見つかりませんでした"; }
```

[Windows]
```powershell
$p=Join-Path $env:APPDATA 'obsidian\obsidian.json'; $vs=@(); if(Test-Path -LiteralPath $p){ $j=(Get-Content -LiteralPath $p -Raw | ConvertFrom-Json); if($j.vaults){ $vs += ($j.vaults.PSObject.Properties | ForEach-Object { $_.Value.path }) } }; $docs=Join-Path $env:USERPROFILE 'Documents'; if(Test-Path -LiteralPath $docs){ $vs += (Get-ChildItem -LiteralPath $docs -Directory -ErrorAction SilentlyContinue | Where-Object { Test-Path (Join-Path $_.FullName '.obsidian') } | ForEach-Object { $_.FullName }) }; $out=@($vs | Where-Object { $_ -and (Test-Path -LiteralPath $_ -PathType Container) } | Select-Object -Unique); if($out.Count -gt 0){ $out -join [Environment]::NewLine } else { 'NG Vault が見つかりませんでした' }
```

- **1件だけ出たら**、それでよいか一言確認してから登録する
- **複数出たら**、番号を振って本人に選んでもらう。**勝手に決めない**
- **0件なら**、Obsidian を使っているか聞く。使っているならパスを教えてもらう

選ばれたパスを `~/.totonoe/config.json` の `vault_path` に**足す**
（`token` を消さないこと。読んで書き戻す）。存在しないフォルダなら書かずに知らせる。

### 「Obsidian の連携を外して」と言われたら

`~/.totonoe/config.json` から `vault_path` の**キーだけ**を消す（`token` は残す）。
Dock 側には何も無いので、これで完全に外れる。

### 読むとき

Vault のパスが `~/.totonoe/config.json` の `vault_path` にあれば、そこも材料にできる。
**規約どおりに書かれていなくても動く。** あれば使う、無ければ中身で判断する。

### どこを読むか

まずフォルダを見て、当てはまる方を選ぶ:

- **規約どおりの構成がある**（`01_デイリーノート/` `02_カード/` など）
  → デイリーノートは**当日分だけ**、カードは `status: active` のものだけ
- **無い / 分からない**
  → 最近更新された `.md` を数件。**どこを読むか本人に確認してから**にする

**読まないもの:** フォルダ名に「保管庫」「過去」「archive」「old」が含まれるもの、
フロントマターが `status: archived` のもの、`.obsidian/` `.git/`、
そして**日記のうち私生活・家族・健康の記述**。

### どう扱うか

- フロントマターに `type` があれば尊重する（`decision` → 決定 / `card` `reference` → 知識）。
  **無ければ中身で判断する**（日報でやっているのと同じ）
- `02_カード/Companies/` のようにフォルダが会社名の一覧になっている場合、
  そこにある名前を**登録の候補として本人に見せる**。**会社を勝手に作らない**（登録は人がやる）
- 判定基準は日報の蒸留と同じ:
  **未来の別セッション・別Agentから引く価値があるか**。件数の上限は無い。0件でよい
- **全文を送らない。** quote はその判断の根拠になった**該当行だけ**を原文のまま
- Vault から拾ったものには `"origin": "obsidian"` を付ける。
  Dock は Vault の存在を知らないので、これが「実際に動いている」唯一の印になる

### 一度提案したものを、翌日また出さない

送る前に必ず `GET /api/agent/context` を読み、**意味で**重複を確かめる。
Vault のノートは消えずに残るので、これを飛ばすと毎日同じカードを提案し続けることになる。

## 3種類の判別

| | 意味 | 例 |
|---|---|---|
| **tasks** | これからやること（期限があり、完了する） | 見積もりを送る／納期を確認する |
| | ↑ 初回は特に拾い漏らさないこと。ここが空だとボードに何も出ない。ただし**実在するものだけ** | |
| **decisions** | 人間が決めたこと（覆るまで有効） | 価格はこの線で進める／今回は断る |
| **knowledge** | 今後も使える事実・ルール・関係性 | A社は月末締め／この配信は返信不要 |

**相手の約束を自社のTaskにしない。** 「A社が金曜に回答する」は Context（knowledge）。
自社の仕事にするなら「金曜にA社の回答を確認する」（tasks）。

## 残さないもの（最重要）

**目的は記憶を増やすことではなく、会社のContextのS/N比を上げること。**

- 雑談・感想・一時的な思考／ブレスト途中の案／撤回された案（「やっぱりナシ」）
- **AI（あなた）自身の推測・提案**（人間が採用と言っていないもの）
- 一般知識（TOTONOEでなくても分かること）／既にあること
- **password・token・APIキー等の認証情報／家族・健康・私生活／他社の秘密**

判断基準は「新しく入った社員に、初日に紙で渡すか」。

**Decision と断定してはいけない語**: 「〜かもしれない」「〜しようかな」「例えば」「仮に」「〜もアリ」。
検討中は決定ではない。**迷ったら出さない。候補0件は失敗ではなく、正しい結果。**

## 必ず守ること

1. **quote 必須** — 各候補に、根拠になった**会話中の実際の発言**を入れる。
   要約や言い換えではなく、本人が言った言葉。出所のない記憶は受け付けられない（APIが拒否する）
2. **勝手にEntityを作らない** — company / person は既存に当たった時だけ書く。
   無ければ**省略する**。間違って紐付くより、紐付かない方が正しい。
   帰属が1つも無い候補はAPIが「未登録Entityのため送れませんでした」と返す。**登録するかは人間が決める**。
   `project` だけは例外で、一覧に無い名前を書いてよい（上記）。書いても案件は作られず、
   承認する人に「この名前でまとめますか」と見えるだけ。**作るかどうかを決めるのは、やはり人間**
3. **推測と事実を分ける** — 推測は提案しない。事実だけを、本人の言葉とともに送る
4. **承認しない** — 承認は人間がブラウザで行う。提案の結果に承認先（https://app.totonoedock.com）を添えてユーザーへ伝える
5. **勝手に送らない** — ユーザーが「残して」と言ったとき、または区切りで
   「TOTONOEに残しますか？」と聞いて同意を得たときだけ実行する

## 送ったあとにユーザーへ伝えること

- 何を候補にしたか（種類とタイトル）
- **あえて残さなかったもの**があれば一言（例:「価格の別案は検討中とみて残していません」）
- 承認は https://app.totonoedock.com のトップ最上段から、と伝える

## この版に無いもの

仕事の状態更新（進行中→相手待ち→完了）は v0.1 のAPIには含まれていません。
「終わった」「返事待ち」と言われたら、**Board で直接動かしてください**と案内する。
