\|auto` | The language you speak, as an ISO 639-1 code (default `en`). `auto` lets the service tell each sentence's language, for a user who mixes two. |
| `--permission-mode acceptEdits\|manual` | How Claude Code asks (default `acceptEdits`). `bypassPermissions` is refused: approvals would never reach you. |
| `--auto-mode` | Each agent approves what it judges safe, Claude Code in its auto permission mode and Codex through its `auto_review` reviewer; TapQ asks you the rest. Off by default. |
| `--subscription claude` | Claude Code signs in with your claude.ai subscription instead of an API key from the environment. Checked at start. Off by default; Anthropic's terms govern using a subscription login through another tool, so check them first. |
| `--agents ` | Only these agents may start: `claude`, `codex`. Both by default. |
| `--realtime-endpoint ` | A server that speaks OpenAI's Realtime wire, for the voice sessions. |
| `--openai-base-url ` | A base URL for the text models instead of `https://api.openai.com/v1`. |
Exit status: 0 is a clean stop, 64 a usage error (nothing started), and 70 a fatal or a
refused start, with one `tapq-kernel: fatal in : ` line on standard
error.
Standard output carries one JSON status line per change, for a program that hosts the
kernel. Standard input is that host's lifeline: its end of file stops the kernel.
## Configuration
| Variable | Default | |
|---|---|---|
| `TAPQ_OPENAI_API_KEY` | none | Required. Every voice session and text-model call runs on it. |
| `TAPQ_CLAUDE_MODEL` | `claude-haiku-5-5` | The model Claude Code is started on, whatever your own settings say. |
| `TAPQ_CODEX_MODEL` | `gpt-5.6-luna` | The model Codex's threads use. |
| `TAPQ_INTENT_MODEL`, `TAPQ_SUMMARY_MODEL`, `TAPQ_COMMAND_MODEL`, `TAPQ_PROGRESS_MODEL`, `TAPQ_TITLER_MODEL`, `TAPQ_PICKER_MODEL` | `gpt-5.6-luna` | TapQ's own text models: routing, reply summaries, command descriptions, status, conversation titles, and which conversation your words carry on. |
| `TAPQ_STT_MODEL` | `gpt-4o-transcribe` | Speech to text. |
| `TAPQ_TTS_MODEL`, `TAPQ_TTS_VOICE` | `gpt-realtime-2.1-mini`, `cedar` | TapQ's voice. |
| `TAPQ_DEBUG` | off | `1` puts every diagnostic on standard error, not only warnings and errors. |
| `TAPQ_ALLOW_UNSUPPORTED_AGENT_VERSIONS` | off | `1` runs an agent outside the supported range, with a warning. |
| `TAPQ_BROKER_DIR` | see below | Where TapQ keeps its state. |
TapQ keeps each folder's state in `~/Library/Application Support/TapQ/runtime/kernel/`,
in a directory named by a hash of the folder's path and created `0700`: the journal (what
you said to each agent, verbatim, and what came of it), the agents' session ids, and
`diagnostics.log`.
## Privacy and data
- **Your voice goes to OpenAI.** Microphone audio streams to OpenAI's Realtime API for
transcription for as long as `tapq-kernel run` runs, and TapQ's sentences are voiced there.
- **So do the words around it.** What you say, and what the agents ask and reply, goes to
OpenAI's Responses API for routing, summaries, command descriptions, status and
conversation titles.
- **All of it on your key**, under your OpenAI account's terms. TapQ talks to no other
service unless you name one with `--realtime-endpoint` or `--openai-base-url`, opens no
network port, and keeps no copy of the audio.
- **The agents stay on their own accounts.** Claude Code and Codex run as they would in your
terminal, started without TapQ's variables or its key.
- **Nothing is approved without you.** An approval comes only from your answer to a request
you heard, unless you turn on `--auto-mode`, where the agents' own reviewers decide first.
## How it works
The kernel is one loop. Speech comes in as utterances; a text model turns each into one
action for one agent; a deterministic gate lets an answer through only for a request the
user heard; the agent runs as a child process; what it asks and says is queued and spoken.
Each step is written to the folder's journal, so a restart can say what was lost.
| Target | What it holds |
|---|---|
| `TapQKernel` | The loop: the journal, the gate, every sentence TapQ speaks, the status channel. No Apple framework, network or subprocess. |
| `TapQKernelClaude` | Claude Code as a stream-json delegate. |
| `TapQKernelCodex` | Codex as a JSON-RPC delegate over `codex app-server`. |
| `TapQOpenAI` | The text models, over the Responses API. |
| `TapQVoiceIO`, `TapQVoiceBackends` | Speech in and out over OpenAI's Realtime API. |
| `TapQAudioIO`, `TapQAudioCaptureBridge` | Microphone capture and playback (macOS). |
| `TapQPOSIXSupport` | Child processes in their own process groups, and line channels. |
| `TapQContracts` | Types and protocols the targets share. |
| `tapq-kernel` | The executable: command line, startup checks, composition. |
Everything but the audio targets builds and tests on Linux; `tapq-kernel run` needs macOS.
## Development
```bash
swift build
swift test
scripts/check-release-version.sh
scripts/check-public-boundary.sh # needs ripgrep
```
On a Mac with only the Command Line Tools there is no XCTest, so `swift test` cannot run.
Build with `swift build --build-system native`, then use `scripts/typecheck-tests.sh` and
`scripts/host-test.sh ...` instead. [CONTRIBUTING.md](CONTRIBUTING.md) has the
rest, and [TROUBLESHOOTING.md](TROUBLESHOOTING.md) covers a start that fails.
## Community
- **Found a bug?** Open an [issue](https://github.com/spaceamoeba-t/tapq/issues) with the
TapQ version, macOS version, and the agent and its version.
- **Found a vulnerability?** Report it privately, as the [security policy](SECURITY.md)
describes. Please do not open a public issue for it.
- **Questions and ideas** go to
[Discussions](https://github.com/spaceamoeba-t/tapq/discussions).
## License
TapQ source code and documentation are licensed under the
[Apache License 2.0](LICENSE); see [NOTICE](NOTICE) for attribution. The license does
not grant rights to the TapQ name or marks, and the artwork in `assets/brand/` is
separately reserved; see [TRADEMARKS.md](TRADEMARKS.md).