diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..0ccc034 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,30 @@ +name: 不具合 +description: 動きがおかしい +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + 思いついた時点で 1 行だけでも構いません。足りない分は消化するときに埋めます。 + - type: textarea + id: what + attributes: + label: 何が起きたか + placeholder: ⌘W でセッションが閉じない + validations: + required: true + - type: textarea + id: evidence + attributes: + label: 手がかり + description: | + あれば。スクリーンショット、または記録の 1 行。 + `TERMIT_FRAME_LOG=1 RUST_LOG=info termit`(描画・読み取り) + `TERMIT_KEYLOG=/tmp/keys.log termit`(押したキーとその解釈) + placeholder: | + 描く面を取れなかった: 間に合わず=0 隠れて=26 作り直し=0 + - type: input + id: build + attributes: + label: どの版か + placeholder: v0.1.0 / main の 920b7ad diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..afdca7d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,3 @@ +# 空の issue を残す。思いついたことを 1 行で放り込めないと、 +# 昼のあいだに捕まらず、そのまま消える。 +blank_issues_enabled: true diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..2b0e6b0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,27 @@ +name: ほしい機能 +description: できるようにしたいこと +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + 思いついた時点で 1 行だけでも構いません。 + - type: textarea + id: problem + attributes: + label: 困っていること + description: 解決策ではなく、困りごとのほうを書きます。作り方は消化するときに決めます。 + placeholder: エージェントが 6 本動いていると、どれが返事待ちか分からない + validations: + required: true + - type: dropdown + id: scope + attributes: + label: 端末の仕事か + description: | + termit は「プロセスを起こす・PTY を中継する・エスケープ列を解釈する・描く」までを担います。 + 迷ったら「わからない」で構いません。消化するときに一緒に考えます。 + options: + - 端末の仕事だと思う + - 端末の外でもできるかもしれない + - わからない diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..156aa5f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,63 @@ +# termit + +A macOS terminal for working with coding agents. Rust, one binary, no runtime. + +## Scope + +termit spawns processes, relays the pty, interprets escape sequences and draws +the result. It does not manage conversations, drive an agent, or run workflows. +Anything that needs the terminal to understand what an agent is *doing* belongs +outside it. + +Before adding a feature, read `## Why` and `## Not goals` in the README. If the +change does not fit them, say so rather than quietly widening the scope. + +## Rules live in config, not in the binary + +Nothing in the code knows what Claude Code or Codex look like. Agent state is +matched against `[agent]`, paste redaction against `[paste]`. When an upstream +tool changes its wording, the fix is a config edit, not a release. Keep it that +way: if you are about to hard-code a vendor's key shape or prompt text, put it +in a default table instead. + +## Workflow + +- Branch, then PR, then wait for CI, then `gh pr merge --squash --delete-branch`. + **Never commit to `main`.** +- Commit messages and PR bodies in **English**. Code comments and `docs/` in + **Japanese**. +- One issue, one branch, one PR. + +## Measure before you diagnose + +Reasoning from the code has produced the wrong cause more than once here; a +measurement has found it every time. Build the measurement first. + +| Tool | What it answers | +|---|---| +| `TERMIT_FRAME_LOG=1` with `RUST_LOG=info` | per-frame timings, surface failures by reason, which rows were drawn | +| `--bench` | cost of building and submitting a frame | +| `--throughput` | how fast bytes from the pty are consumed | +| `--latency-test` | input round trip, no keyboard needed | +| `--probe out.png` | render one frame offscreen (screen capture is blocked here) | +| `--keytest` | what a key press actually arrives as | + +State what you measured. If you could not measure something, say that instead +of estimating and presenting it as a result. + +## Tests + +Tests sit next to the thing they cover and are named in Japanese, as sentences +about behaviour. Prefer a pure function over a test that needs a window or a +pty: `secret.rs` and `input.rs` are testable because the decisions were pulled +out of the event loop. + +Before claiming a fix works, run `cargo test`, `cargo clippy --all-targets -- +-D warnings` and `cargo fmt --check`, and check that the new test fails when +the fix is reverted. + +## Docs + +`docs/references/*.md` record what other implementations do and which parts +termit took, with the reason for each rejection. Add to them when you research +something rather than leaving it in a PR body. diff --git a/README.md b/README.md index 69cdeb6..73a7c9a 100644 --- a/README.md +++ b/README.md @@ -467,6 +467,7 @@ The detailed design record is in Japanese. - [`docs/superpowers/specs/2026-09-08-agent-terminal-design.md`](docs/superpowers/specs/2026-09-08-agent-terminal-design.md) — the specification - [`docs/performance.md`](docs/performance.md) — where the time actually goes, measured - [`docs/references/performance-techniques.md`](docs/references/performance-techniques.md) — techniques taken from other terminals, each marked adopted, rejected with the measurement, or still open +- [`docs/issue-workflow.md`](docs/issue-workflow.md) — collecting work as issues during the day and clearing them in one sitting - [`docs/references/paste.md`](docs/references/paste.md) — what iTerm2 does at the paste boundary, and which half of it termit took - [`docs/references/agent-state.md`](docs/references/agent-state.md) — how other tools tell a working agent from one that is waiting for you, and which parts of that termit adopted - [`docs/references/sandbox.md`](docs/references/sandbox.md) — how agents are sandboxed elsewhere, what Apple's `container` measured at, and what termit deliberately leaves outside diff --git a/docs/issue-workflow.md b/docs/issue-workflow.md new file mode 100644 index 0000000..ba5b32b --- /dev/null +++ b/docs/issue-workflow.md @@ -0,0 +1,130 @@ +# issue の貯め方と消化のしかた + +作成日:2026-09-17 + +思いついたことを昼のあいだ issue に貯め、夕方以降にまとめて片づける。 +その形にした理由と、実際の手順。 + +## なぜ貯めるのか + +**手を止める費用のほうが高い。** 端末を使っている最中に「⌘W が効かない」と気づいて +そのまま直しはじめると、元の作業の文脈が失われる。気づきは 10 秒で捨てられる場所に +置き、直すのはまとめてやるほうが、一日の総量が増える。 + +**夕方に寄せる理由が 2 つある。** 利用の上限は時間で回復するので、日中に使い切っても +夕方には戻っている。そして Claude Code は、**セッションを開いたままにしておけば +回復した時点で自分から作業を拾い直す**(`autoContinueAtUsageLimit`、既定で有効)。 +待っているあいだに終了・再起動すると、その予約は消える。 + +**issue に置く理由。** 作業ツリーから独立している。ブランチを切り替えても、 +機械を変えても、一覧はそこにある。手元の TODO ファイルだと、 +複数のエージェントが同じ行を書き換えて壊す。これは並行作業での破損の最大要因である。 + +## 昼:捕まえるだけ + +**1 行でよい。** 分類も再現手順も要らない。 + +```sh +gh issue create --title "⌘W でセッションが閉じない" +``` + +型(`.github/ISSUE_TEMPLATE/`)はわざと軽くしてある。空の issue も許してある。 +**捕まえる手間が重いと、昼のあいだに捕まらず、そのまま消える。** + +手がかりがその場にあるなら貼る。あとで再現するより、そのときの 1 行が速い。 + +```sh +# 描画・読み取りの記録 +RUST_LOG=info TERMIT_FRAME_LOG=1 termit +# 押したキーと、その解釈 +TERMIT_KEYLOG=/tmp/keys.log termit +``` + +## 夕方その 1:仕分ける + +消化の前に、**全部まとめて 15 分**で仕分ける。1 件ずつ着手しながら考えない。 + +```sh +gh issue list --state open +``` + +各件について 3 つだけ決める。 + +1. **そのまま着手できるか。** できないなら、足りないのは何か。 + 多くは「測っていない」である。ここで測る。**原因の見当をコードから立てない** —— + このリポジトリでは、それで 2 回外している(`docs/performance.md` 7.9、 + Docker 経由のコピーの件)。 +2. **termit の仕事か。** 端末の責務を超えるものは、超えると書いて閉じる。 + 閉じた理由は残す。同じ提案がまた来る。 +3. **順番。** 直したものが次の土台になる並びにする。 + +仕分けの結果は issue のコメントに書く。夕方の自分と、明日のエージェントが読む。 + +## 夕方その 2:消化する + +**1 issue = 1 ブランチ = 1 PR。** 1 本の PR に 2 件入れない。片方で CI が落ちると +両方止まる。レビューもできない。 + +```sh +git checkout -b fix-close-on-cmd-w +# 直す。テストを先に落としてから直す。 +cargo test && cargo clippy --all-targets -- -D warnings && cargo fmt --check +gh pr create --title "..." --body "... Closes #12" +gh pr checks --watch +gh pr merge --squash --delete-branch +``` + +本文に `Closes #12` と書くと、マージで issue が閉じる。手で閉じない。 + +**並行してやるなら worktree を使う。** 同じ作業ディレクトリで 2 本動かすと、 +互いのファイルを踏む。 + +```sh +git worktree add ../termit-issue-12 -b fix-issue-12 +``` + +**止まったら、止まったと書く。** 分かったことを issue に残して次へ行く。 +半端な PR を開いたままにしない。 + +## 自動に任せる場合 + +`@claude` に投げる形もある。導入は `claude` の中で `/install-github-app` +(`gh` の認証が済んでいること、リポジトリの管理権限が要る)。秘密鍵として +`ANTHROPIC_API_KEY` か `CLAUDE_CODE_OAUTH_TOKEN`(`claude setup-token` で作る)が +リポジトリに入る。以後、issue やコメントで `@claude …` と書けば、Claude が +読んで PR まで作る。 + +**このリポジトリには workflow を置いていない。** 秘密鍵が要り、走らせれば +その都度 GitHub Actions の時間とトークンを使う。導入するかは持ち主が決めることなので、 +手順だけ書いてある。 + +入れる場合に効く制限(費用が青天井にならないようにする)。 + +- `claude_args: --max-turns 5` +- workflow に `timeout-minutes` +- `concurrency` で同時実行を絞る +- **型で文脈を先に渡す。** 往復が減るぶん、そのまま費用が減る + +**線引き。** 自動に向くのは、正解が機械で確かめられるもの(テストが落ちている、 +lint が落ちている、綴りの直し)。向かないのは、**何を作るべきかの判断が要るもの**。 +termit では後者が多い。上の「termit の仕事か」を機械に決めさせない。 + +## 他所から取ったこと + +| 取ったこと | 出どころ | +|---|---| +| issue を、作業ツリーから独立した調整面として使う | 複数エージェント運用の通例 | +| 1 つの計画ファイルを複数で編集しない(= 1 issue 1 ブランチ) | 並行作業での破損の最大要因として報告されている | +| `CLAUDE.md` に規範を置き、簡潔に保つ(毎回読まれる) | [GitHub Actions の推奨](https://code.claude.com/docs/en/github-actions#best-practices) | +| 型で文脈を先に渡して往復を減らす | 同上(費用の節に明記されている) | +| 調べる → 決める → 作る → 見直す → 出す | 主要な運用手順に共通する形 | + +**取らなかったもの:重い型。** 再現手順・期待結果・環境を必須にする型は、 +報告の質は上がるが、**思いつきを捨てる場所としては重すぎる**。 +このリポジトリは一人で回しているので、質は夕方の仕分けで上げるほうが合う。 + +## 参考 + +- [Claude Code GitHub Actions](https://code.claude.com/docs/en/github-actions) +- [claude-code-action の例](https://github.com/anthropics/claude-code-action/tree/main/examples) +- [Git worktrees と並行エージェント](https://www.developersdigest.tech/blog/git-worktrees-claude-code-parallel-agents-guide)