Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 空の issue を残す。思いついたことを 1 行で放り込めないと、
# 昼のあいだに捕まらず、そのまま消える。
blank_issues_enabled: true
27 changes: 27 additions & 0 deletions .github/ISSUE_TEMPLATE/feature.yml
Original file line number Diff line number Diff line change
@@ -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:
- 端末の仕事だと思う
- 端末の外でもできるかもしれない
- わからない
63 changes: 63 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
130 changes: 130 additions & 0 deletions docs/issue-workflow.md
Original file line number Diff line number Diff line change
@@ -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 <branch> --watch
gh pr merge <n> --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)
Loading