@codefilabs/tq 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codefilabs/tq",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "A lightweight task queue runner that spawns Claude AI tasks as independent tmux sessions",
5
5
  "keywords": [
6
6
  "claude",
@@ -3,66 +3,92 @@ name: tq
3
3
  description: >
4
4
  This skill should be used when the user asks to "add to queue", "run queue", "queue these tasks",
5
5
  "schedule with tq", "tq status", "check task queue", "create a tq queue", "set up cron for tq",
6
- "run claude in background", "batch prompts in tmux", "start a conversation", "converse via telegram",
7
- "telegram conversation mode", or wants to manage Claude prompts running in tmux sessions via the
8
- tq CLI tool. Triggers on phrases like "queue", "tq", "task queue", "tmux queue", "scheduled claude tasks",
9
- "conversation mode", "telegram chat", "converse".
10
- version: 1.1.0
6
+ "run claude in background", "batch prompts in tmux", "start a conversation", "start conversation mode",
7
+ "converse via telegram", "telegram conversation mode", "telegram bot", "message routing",
8
+ "route a message", "spawn a session", "orchestrator", "reset tasks", "reset queue",
9
+ "notify on completion", "tq notification", "tq health", "check tq health", "tq setup",
10
+ "setup telegram bot", "tq install", or wants to manage Claude prompts running
11
+ in tmux sessions via the tq CLI tool. Triggers on phrases like "queue", "tq", "task queue",
12
+ "tmux queue", "scheduled claude tasks", "conversation mode", "telegram chat", "converse",
13
+ "telegram session", "poll telegram", "tq-converse", "tq-message", "task notification".
14
+ version: 1.5.0
11
15
  ---
12
16
 
13
- # tq Claude Task Queue Runner
17
+ # tq -- Claude Task Queue Runner
14
18
 
15
19
  Script: `${CLAUDE_PLUGIN_ROOT}/scripts/tq`
16
20
 
17
- Installed to PATH via `/install`: `/opt/homebrew/bin/tq`
21
+ Installed to PATH via `/install` (typically `/opt/homebrew/bin/tq` or `/usr/local/bin/tq`; use `command -v tq` to resolve)
18
22
 
19
23
  ## Overview
20
24
 
21
25
  tq manages Claude Code sessions via tmux in two modes:
22
- 1. **Queue mode** — batches prompts into YAML queue files, spawns each as an independent tmux session. Idempotent — running `tq` again skips `done` and live `running` tasks.
23
- 2. **Conversation mode** persistent interactive Claude Code sessions orchestrated via Telegram. An orchestrator routes messages to the right conversation, creating new sessions or resuming existing ones.
26
+
27
+ 1. **Queue mode** -- batch prompts into YAML queue files, spawn each as an independent tmux session. Idempotent: re-running `tq` skips `done` and live `running` tasks.
28
+ 2. **Conversation mode** -- maintain persistent interactive Claude Code sessions orchestrated via Telegram. An orchestrator routes messages to the right conversation, spawning new sessions or resuming existing ones.
24
29
 
25
30
  ## Queue File Format
26
31
 
27
32
  Location: `~/.tq/queues/<name>.yaml`
28
33
 
29
34
  ```yaml
30
- cwd: /path/to/working/directory # optional where claude runs for each task
35
+ schedule: "0 9 * * *" # optional -- auto-managed crontab via tq-cron-sync
36
+ reset: daily # optional -- daily|weekly|hourly|always|on-complete
37
+ cwd: /path/to/working/directory # where claude runs for each task
38
+ message: # optional -- notification config
39
+ service: telegram
40
+ content: summary # summary|status|details|log
31
41
  tasks:
32
- - prompt: fix the login bug in auth service
42
+ - name: review-auth # optional -- used for session naming
43
+ prompt: fix the login bug in auth service
33
44
  - prompt: write unit tests for payment module
34
45
  ```
35
46
 
36
- Queue files are **read-only** tq never modifies them.
47
+ Queue files are read-only -- tq never modifies them.
48
+
49
+ ### Reset Modes
50
+
51
+ Reset controls when task state is cleared so tasks re-run:
52
+
53
+ | Mode | Behavior |
54
+ |------|----------|
55
+ | `daily` | Clear once per calendar day |
56
+ | `weekly` | Clear once per ISO week |
57
+ | `hourly` | Clear once per hour |
58
+ | `always` | Clear on every `tq` run |
59
+ | `on-complete` | Per-task: delete state after task finishes |
37
60
 
38
61
  ## State
39
62
 
40
- State dir: `~/.tq/queues/.tq/<queue-basename>/`
41
- One file per task, named by 8-char shasum of the prompt:
63
+ State dir: `<queue-dir>/.tq/<queue-basename>/` (e.g., `~/.tq/queues/.tq/morning/`)
64
+ One file per task, named by 8-char SHA-256 of the prompt:
42
65
 
43
66
  ```
44
67
  status=running
45
- session=fix-the-login-23451
68
+ session=tq-fix-the-login-451234
46
69
  window=fix-the
47
70
  prompt=fix the login bug in auth service
48
71
  started=2026-03-05T10:00:00
49
72
  ```
50
73
 
51
- Statuses: `pending` `running` `done`
74
+ Statuses: `pending` -> `running` -> `done`
52
75
 
53
76
  ## Commands
54
77
 
55
78
  | Command | Purpose |
56
79
  |---------|---------|
57
- | `/todo <natural language>` | Create/update queue + optionally schedule |
80
+ | `/todo <natural language>` | Create/update queue and optionally schedule |
58
81
  | `/schedule <natural language>` | Add/update cron schedule for a queue |
59
82
  | `/pause <queue>` | Remove run line, keep status-check (resume with `/schedule`) |
60
83
  | `/unschedule <queue>` | Remove all cron lines for a queue |
61
84
  | `/jobs [filter]` | List all scheduled tq cron jobs |
62
- | `/health [queue]` | System-wide diagnostics |
85
+ | `/health [queue]` | Run system-wide diagnostics |
63
86
  | `/install` | Symlink tq binaries to PATH |
64
- | `/converse [start\|stop\|status]` | Manage Telegram conversation sessions |
87
+ | `/init` | Configure workspace directories and build project catalog |
88
+ | `/review` | Lint and review staged changes before commit |
89
+ | `/converse [start\|stop\|status\|list]` | Manage conversation orchestrator and sessions |
65
90
  | `/tq-reply` | Send response back to Telegram (conversation mode) |
91
+ | `/tq-message` | Write and send task completion summary |
66
92
  | `/setup-telegram` | Configure Telegram bot token and notifications |
67
93
 
68
94
  ## CLI Usage
@@ -72,73 +98,77 @@ tq <queue.yaml> # spawn pending tasks in tmux; skip running/done
72
98
  tq --status <queue.yaml> # print status table; flip dead sessions to done
73
99
  ```
74
100
 
75
- ## Crontab Pattern
101
+ ## Cron Scheduling
102
+
103
+ Add `schedule:` to any queue YAML and `tq-cron-sync` auto-manages crontab (runs every 20 min, scans `~/.tq/queues/*.yaml`). Each scheduled queue gets two cron lines:
76
104
 
77
105
  ```cron
78
- 0 9 * * * /opt/homebrew/bin/tq ~/.tq/queues/morning.yaml >> ~/.tq/logs/tq.log 2>&1
79
- */30 * * * * /opt/homebrew/bin/tq --status ~/.tq/queues/morning.yaml >> ~/.tq/logs/tq.log 2>&1
106
+ <schedule> $(command -v tq) ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1
107
+ */30 * * * * $(command -v tq) --status ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1
80
108
  ```
81
109
 
82
- The `tq --status` cron runs every 30 min to reap dead sessions and flip their state to `done`.
110
+ The `tq --status` line runs every 30 min to reap dead sessions and flip their state to `done`.
111
+
112
+ See `references/cron-expressions.md` for natural language to cron mapping.
83
113
 
84
114
  ## Queue Name Inference
85
115
 
86
116
  When using `/todo` without an explicit queue name:
87
117
 
88
- - Schedule keyword present use it: "every morning" `morning`, "daily" `daily`, "weekly" `weekly`
89
- - No schedule use `basename` of current working directory
118
+ - Schedule keyword present -> derive from it: "every morning" -> `morning`, "daily" -> `daily`, "weekly" -> `weekly`
119
+ - No schedule -> use `basename` of current working directory
90
120
 
91
121
  ## Reset
92
122
 
93
123
  - One task: delete its state file from `.tq/<queue-basename>/`
94
124
  - Entire queue: `rm -rf ~/.tq/queues/.tq/<queue-basename>/`
95
125
 
96
- ## Chrome Integration
97
-
98
- tq launches claude with `--chrome` and opens **Chrome Profile 5** (halbotkirchner@gmail.com) automatically before connecting.
99
-
100
- ### Multiple Chrome profiles / extensions
101
-
102
- If you need to interact with a Chrome profile that has a different Claude extension instance (e.g. different account), use the `chrome-devtools` MCP with the `--isolated` flag to run isolated browser extension sessions that don't conflict across profiles.
103
-
104
- ### Setting the browser display name
105
-
106
- The Claude extension stores the browser name as `bridgeDisplayName` in the extension's `chrome.storage.local`. To set it for the first time on a profile:
107
- - Right-click the Claude extension icon in the Chrome toolbar → **Options**
108
- - Or open the sidepanel and look for a settings/gear icon with a name field
109
-
110
126
  ## Conversation Mode
111
127
 
112
- Start an orchestrator: `tq-converse start` or send `/converse` from Telegram.
128
+ Start the orchestrator via `tq-converse start` or send `/converse` from Telegram.
129
+
130
+ The orchestrator routes incoming Telegram messages using 3-tier routing:
113
131
 
114
- The orchestrator routes incoming Telegram messages to the appropriate conversation session:
115
- - Telegram reply to a known message routes to that session automatically
116
- - `#slug message` routes to the named session
117
- - New topic → orchestrator spawns a new session with a descriptive slug
132
+ 1. **Reply threading** -- Telegram reply to a known message routes to that session automatically
133
+ 2. **Slug prefix** -- `#slug message` routes to the named session
134
+ 3. **Orchestrator fallback** -- new topic triggers the orchestrator to spawn a new session with a descriptive slug
118
135
 
119
136
  Each conversation is a persistent Claude Code interactive session in its own tmux window.
120
137
  Child sessions use `/tq-reply` to send responses back to Telegram as threaded replies.
121
138
 
122
- ### Conversation CLI
139
+ ### Key CLI commands
123
140
 
124
141
  ```bash
125
142
  tq-converse start # start orchestrator
126
- tq-converse spawn <slug> --cwd <dir> # new conversation session
127
- tq-converse route <slug> <message> # send to a session
143
+ tq-converse spawn <slug> --cwd <dir> # create new conversation session
144
+ tq-converse route <slug> <message> # send message to a session
128
145
  tq-converse list # list active sessions
146
+ tq-converse status # show all session statuses
129
147
  tq-converse stop [<slug>] # stop session or orchestrator
130
148
  ```
131
149
 
132
- ### Telegram Commands
150
+ ## Background Scripts
133
151
 
134
- | Command | Purpose |
135
- |---------|---------|
136
- | `/converse` | Start the orchestrator |
137
- | `/stop [slug]` | Stop orchestrator or a specific session |
138
- | `/status` | Show all sessions |
139
- | `/list` | List active conversations |
152
+ | Script | Purpose |
153
+ |--------|---------|
154
+ | `tq-cron-sync` | Scans `~/.tq/queues/*.yaml` every 20 min, syncs `schedule:` to crontab |
155
+ | `tq-telegram-poll` | Long-polls Telegram, routes messages via 3-tier routing |
156
+ | `tq-telegram-watchdog` | Ensures poll cron entry exists |
157
+ | `tq-message` | Sends notifications (Telegram/Slack) on task completion |
158
+
159
+ ## Troubleshooting
160
+
161
+ | Problem | Likely Cause | Fix |
162
+ |---------|-------------|-----|
163
+ | Tasks stuck in `running` | tmux session died | Run `tq --status <queue>` to reap dead sessions |
164
+ | `tq` command not found | Not installed to PATH | Run `/install` |
165
+ | Queue runs but nothing happens | All tasks already `done` | Delete state: `rm -rf <queue-dir>/.tq/<name>/` |
166
+ | Cron not firing | `tq-cron-sync` not running or schedule missing | Check `crontab -l \| grep tq` and add `schedule:` to queue YAML |
167
+ | Telegram messages not routing | Orchestrator not running | Run `/converse start` |
168
+ | Malformed YAML | Parser does not support anchors | Use only `cwd`, `tasks`, `schedule`, `reset`, `message` top-level keys |
140
169
 
141
170
  ## Additional Resources
142
171
 
143
- - **`references/session-naming.md`** Session/window name generation algorithm and examples
144
- - **`references/cron-expressions.md`** Natural language cron expression mapping table
172
+ - **`references/session-naming.md`** -- session/window name generation algorithm and examples
173
+ - **`references/cron-expressions.md`** -- natural language to cron expression mapping table
174
+ - **`references/chrome-integration.md`** -- Chrome `--chrome` flag, profile setup, and browser configuration
@@ -0,0 +1,52 @@
1
+ # tq Chrome Integration Reference
2
+
3
+ ## When to Use Chrome
4
+
5
+ Chrome integration is for tasks that interact with web pages (scraping, form filling, visual verification). Most queue tasks that only modify code do **not** need Chrome.
6
+
7
+ ## How `--chrome` Works
8
+
9
+ When a queue task runs, tq generates a `.launch.py` launcher script that:
10
+
11
+ 1. Opens Chrome with the configured profile directory
12
+ 2. Passes `--chrome` to the `claude` CLI, connecting to the Chrome browser extension
13
+ 3. Claude interacts with web pages through the browser
14
+
15
+ ```python
16
+ # In the generated .launch.py:
17
+ subprocess.Popen(["open", "-a", "Google Chrome", "--args", "--profile-directory=<ProfileDir>"])
18
+ time.sleep(2)
19
+ os.execvp('claude', ['claude', '--settings', settings_file, '--dangerously-skip-permissions', '--chrome', prompt])
20
+ ```
21
+
22
+ Note: `subprocess.Popen` is correct here (launches Chrome as a sibling process). `os.execvp` replaces the Python process with Claude (per `anti-patterns.md`).
23
+
24
+ ## Chrome Profile Configuration
25
+
26
+ The Chrome profile directory is hardcoded in `scripts/tq` in the launcher generation section. To find which profile directory maps to which account:
27
+
28
+ ```bash
29
+ for d in ~/Library/Application\ Support/Google/Chrome/Profile*/; do
30
+ python3 -c "import json; p=json.load(open('$d/Preferences')); print('$(basename $d):', p.get('account_info',[{}])[0].get('email','unknown'))" 2>/dev/null
31
+ done
32
+ ```
33
+
34
+ To use a different profile, edit the `--profile-directory` argument in `scripts/tq`. The profile is not yet configurable per-queue.
35
+
36
+ ## Browser Display Name
37
+
38
+ The Claude browser extension identifies itself via `bridgeDisplayName` in `chrome.storage.local`. Set it via the extension's Options page (right-click extension icon > Options).
39
+
40
+ ## Troubleshooting
41
+
42
+ | Problem | Cause | Fix |
43
+ |---------|-------|-----|
44
+ | Chrome doesn't open | Chrome not installed or not at expected path | Verify: `ls /Applications/Google\ Chrome.app` |
45
+ | Extension not connecting | Claude extension not installed in the target profile | Install the Claude Code extension in Chrome, then retry |
46
+ | Wrong profile used | Hardcoded profile doesn't match intended account | Run the profile discovery command above, update `scripts/tq` |
47
+ | `--chrome` flag ignored | Task launched without Chrome integration | Check the launcher generation section in `scripts/tq` |
48
+
49
+ ## Related
50
+
51
+ - **SKILL.md** — overview of tq modes and CLI usage
52
+ - **session-naming.md** — how tmux session names are derived
@@ -1,20 +1,29 @@
1
1
  # tq Cron Expression Reference
2
2
 
3
- ## Natural Language Cron Mapping
3
+ All cron expressions use the **system timezone** (check with `date +%Z`). There is no per-queue timezone override.
4
+
5
+ ## Natural Language to Cron Mapping
4
6
 
5
7
  | Natural Language | Cron Expression | Notes |
6
8
  |-----------------|-----------------|-------|
7
9
  | "every morning" / "daily at 9am" | `0 9 * * *` | Default morning time |
8
10
  | "every night" / "nightly" | `0 22 * * *` | 10pm |
9
- | "every weekday" | `0 9 * * 1-5` | MonFri at 9am |
10
- | "every weekday at 6pm" | `0 18 * * 1-5` | MonFri at 6pm |
11
+ | "every weekday" | `0 9 * * 1-5` | Mon-Fri at 9am |
12
+ | "every weekday at 6pm" | `0 18 * * 1-5` | Mon-Fri at 6pm |
11
13
  | "every monday" / "weekly on mondays" | `0 9 * * 1` | 9am Monday |
12
14
  | "every monday at 8am" | `0 8 * * 1` | 8am Monday |
15
+ | "weekends" / "every weekend" | `0 10 * * 0,6` | Sat & Sun at 10am |
13
16
  | "every hour" / "hourly" | `0 * * * *` | Top of each hour |
17
+ | "every 2 hours" | `0 */2 * * *` | Every 2 hours |
14
18
  | "every 4 hours" | `0 */4 * * *` | Every 4 hours |
15
19
  | "every 30 minutes" | `*/30 * * * *` | Every 30 min |
20
+ | "every 15 minutes" | `*/15 * * * *` | Every 15 min |
21
+ | "every 5 minutes" | `*/5 * * * *` | Every 5 min |
22
+ | "twice daily" / "morning and evening" | `0 9,18 * * *` | 9am and 6pm |
23
+ | "business hours" | `0 9-17 * * 1-5` | Every hour 9am-5pm Mon-Fri |
16
24
  | "daily" | `0 9 * * *` | Default to 9am |
17
25
  | "weekly" | `0 9 * * 1` | Default to Monday 9am |
26
+ | "first of the month" | `0 9 1 * *` | 9am on the 1st |
18
27
 
19
28
  ## Day-of-Week Numbers
20
29
 
@@ -28,31 +37,17 @@
28
37
  | 5 | Friday |
29
38
  | 6 | Saturday |
30
39
 
31
- ## Standard tq Crontab Block
32
-
33
- Every scheduled queue gets two cron lines:
34
-
35
- ```cron
36
- # Run queue (spawn pending tasks)
37
- <cron> /opt/homebrew/bin/tq ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1
38
-
39
- # Status sweep (reap dead sessions every 30 min)
40
- */30 * * * * /opt/homebrew/bin/tq --status ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1
41
- ```
42
-
43
- ## Updating Crontab
40
+ ## Crontab Management
44
41
 
45
- Replace existing lines for the same queue:
42
+ `tq-cron-sync` automatically manages crontab entries — see SKILL.md for details. For manual override, filter out old entries before appending:
46
43
 
47
44
  ```bash
48
- (crontab -l 2>/dev/null | grep -v "tq.*<name>.yaml"; \
49
- echo "<cron> /opt/homebrew/bin/tq ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1"; \
50
- echo "*/30 * * * * /opt/homebrew/bin/tq --status ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1") | crontab -
45
+ (crontab -l 2>/dev/null | grep -v "tq.*/<name>\.yaml"; \
46
+ echo "<cron> $(command -v tq) ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1"; \
47
+ echo "*/30 * * * * $(command -v tq) --status ~/.tq/queues/<name>.yaml >> ~/.tq/logs/tq.log 2>&1") | crontab -
51
48
  ```
52
49
 
53
- The `grep -v` removes all existing lines referencing this queue before appending the new ones, ensuring no duplicates.
54
-
55
- ## Queue Name → Schedule Name Inference
50
+ ## Queue Name Inference
56
51
 
57
52
  When no queue name is given, infer from the schedule keyword:
58
53
 
@@ -65,3 +60,5 @@ When no queue name is given, infer from the schedule keyword:
65
60
  | "hourly" / "every hour" | `hourly` |
66
61
  | "nightly" / "night" | `nightly` |
67
62
  | no schedule | `basename` of current working directory |
63
+
64
+ Related: `/schedule` and `/todo` use this mapping. `/jobs` displays active schedules.
@@ -2,56 +2,85 @@
2
2
 
3
3
  ## Algorithm
4
4
 
5
- Given a prompt string, derive a tmux session name and window name as follows:
5
+ Given a task, derive a tmux session name and window name. The YAML `name` field takes priority over prompt-derived words.
6
+
7
+ ### Source Text
8
+
9
+ 1. If the task has a `name:` field in the YAML, use that as the full source text
10
+ 2. Otherwise, use the first line of the prompt
6
11
 
7
12
  ### Session Name
8
- 1. Take the first 3 words of the prompt
13
+
14
+ 1. If using `name:` field: take the full field value. If using prompt: take the first 3 words
9
15
  2. Lowercase everything
10
16
  3. Replace any non-`[a-z0-9]` character with `-`
11
- 4. Strip trailing `-` characters
17
+ 4. Strip leading and trailing `-` characters
12
18
  5. Truncate to 20 characters
13
- 6. Append `-<epoch-suffix>` (last 6 digits of Unix epoch)
19
+ 6. Prepend `tq-` and append `-<epoch-suffix>` (last 6 digits of Unix epoch)
20
+
21
+ Result: `tq-<base>-<epoch>`
14
22
 
15
23
  ### Window Name
16
- 1. Take the first 2 words of the prompt
17
- 2. Same lowercasing and character replacement as above
18
- 3. Truncate to 15 characters (no epoch suffix)
24
+
25
+ 1. If using `name:` field: take the full field value. If using prompt: take the first 2 words
26
+ 2. Apply the same lowercasing, character replacement, and dash stripping as above
27
+ 3. Truncate to 15 characters (no prefix, no epoch suffix)
19
28
 
20
29
  ## Examples
21
30
 
31
+ ### Without `name:` field (prompt-derived)
32
+
22
33
  | Prompt | Session | Window |
23
34
  |--------|---------|--------|
24
- | `fix the login bug in auth service` | `fix-the-login-<epoch>` | `fix-the` |
25
- | `write unit tests for payment module` | `write-unit-tests-<epoch>` | `write-unit` |
26
- | `Refactor Auth Module` | `refactor-auth-module-<epoch>` | `refactor-auth` |
27
- | `check LinkedIn saved posts` | `check-linkedin-saved-<epoch>` | `check-linkedin` |
35
+ | `fix the login bug in auth service` | `tq-fix-the-login-451234` | `fix-the` |
36
+ | `write unit tests for payment module` | `tq-write-unit-tests-451234` | `write-unit` |
37
+ | `Refactor Auth Module` | `tq-refactor-auth-module-451234` | `refactor-auth` |
38
+
39
+ ### With `name:` field
40
+
41
+ | Name Field | Session | Window |
42
+ |------------|---------|--------|
43
+ | `review-auth` | `tq-review-auth-451234` | `review-auth` |
44
+ | `Update Readme` | `tq-update-readme-451234` | `update-readme` |
28
45
 
29
46
  ## Bash Implementation
30
47
 
31
48
  ```bash
32
49
  EPOCH_SUFFIX="$(date +%s | tail -c 6)"
33
- SESSION_BASE="$(echo "$PROMPT" | awk '{print $1" "$2" "$3}' \
34
- | tr '[:upper:]' '[:lower:]' \
35
- | tr -cs 'a-z0-9' '-' \
36
- | sed 's/-*$//' \
37
- | cut -c1-20)"
38
- SESSION="${SESSION_BASE}-${EPOCH_SUFFIX}"
39
- WINDOW="$(echo "$PROMPT" | awk '{print $1" "$2}' \
40
- | tr '[:upper:]' '[:lower:]' \
41
- | tr -cs 'a-z0-9' '-' \
42
- | sed 's/-*$//' \
43
- | cut -c1-15)"
50
+
51
+ # With name field:
52
+ if [[ -n "$TASK_NAME_FIELD" ]]; then
53
+ SESSION_BASE="$(echo "$TASK_NAME_FIELD" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-*//' | sed 's/-*$//' | cut -c1-20)"
54
+ WINDOW="$(echo "$TASK_NAME_FIELD" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-*//' | sed 's/-*$//' | cut -c1-15)"
55
+ else
56
+ # Without name field (prompt-derived):
57
+ SESSION_BASE="$(echo "$FIRST_LINE" | awk '{print $1" "$2" "$3}' | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-*//' | sed 's/-*$//' | cut -c1-20)"
58
+ WINDOW="$(echo "$FIRST_LINE" | awk '{print $1" "$2}' | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-*//' | sed 's/-*$//' | cut -c1-15)"
59
+ fi
60
+
61
+ SESSION="tq-${SESSION_BASE}-${EPOCH_SUFFIX}"
44
62
  ```
45
63
 
64
+ ## Edge Cases
65
+
66
+ | Input | Session Base | Reason |
67
+ |-------|-------------|--------|
68
+ | 1-word prompt: `deploy` | `deploy` | Uses the single word as-is |
69
+ | 2-word prompt: `fix bug` | `fix-bug` | Uses both words (fewer than 3) |
70
+ | Empty prompt | (empty string) | Produces `tq--<epoch>` — malformed; avoid empty prompts |
71
+ | Special chars: `fix "the" bug!` | `fix-the-bug-` | Quotes and punctuation replaced with `-` |
72
+ | Very long name field | Truncated to 20 chars | `cut -c1-20` limits length |
73
+
46
74
  ## Notes
47
75
 
48
- - Epoch suffix prevents collision when the same prompt is re-queued after a reset
49
- - tmux session names must not contain `.` or `:` the character replacement handles this
50
- - The `-` separator between base and epoch is always present; if the base ends with `-`, it gets stripped first to avoid `--`
76
+ - The epoch suffix prevents collision when the same prompt is re-queued after a reset
77
+ - tmux session names must not contain `.` or `:` -- the character replacement handles this
78
+ - The `-` separator between base and epoch is always present; if the base ends with `-`, strip it first to avoid `--`
79
+ - The `tail -c 6` approach for epoch suffix always produces 6 digits since Unix timestamps are 10+ digits
51
80
 
52
81
  ## Conversation Mode Session Names
53
82
 
54
- Conversation sessions use a different naming scheme slug-based, no epoch suffix:
83
+ Conversation sessions use a slug-based naming scheme with no epoch suffix:
55
84
 
56
85
  | Type | Pattern | Example |
57
86
  |------|---------|---------|
@@ -59,8 +88,6 @@ Conversation sessions use a different naming scheme — slug-based, no epoch suf
59
88
  | Child session | `tq-conv-<slug>` | `tq-conv-fix-auth` |
60
89
  | Child window | `<slug>` | `fix-auth` |
61
90
 
62
- Slugs are short kebab-case names (2-4 words) chosen by the orchestrator Claude when a
63
- new conversation is created. Examples: `fix-auth-bug`, `refactor-api`, `update-docs`.
91
+ Slugs are short kebab-case names (2-4 words) chosen by the orchestrator Claude when creating a new conversation. Examples: `fix-auth-bug`, `refactor-api`, `update-docs`.
64
92
 
65
- Since there is no epoch suffix, conversation session names are unique by slug. Starting
66
- a session with an already-active slug will reuse the existing session.
93
+ Since there is no epoch suffix, conversation session names are unique by slug. Starting a session with an already-active slug reuses the existing session.