Skip to content

Commit 5fcae53

Browse files
committed
refactor: rename cq to issuebot
1 parent b721e5e commit 5fcae53

11 files changed

Lines changed: 78 additions & 78 deletions

File tree

.goreleaser.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22

33
builds:
44
- main: ./main.go
5-
binary: cq
5+
binary: issuebot
66
env:
77
- CGO_ENABLED=0
88
goos:
@@ -12,7 +12,7 @@ builds:
1212
- amd64
1313
- arm64
1414
ldflags:
15-
- -s -w -X github.com/tinybluerobots/cq/cmd.Version={{.Version}}
15+
- -s -w -X github.com/tinybluerobots/issuebot/cmd.Version={{.Version}}
1616

1717
archives:
1818
- format: tar.gz

README.md

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,62 @@
1-
# cq
1+
# issuebot
22

3-
[![Go Version](https://img.shields.io/badge/Go-1.26-blue?logo=go)](https://pkg.go.dev/github.com/tinybluerobots/cq)
3+
[![Go Version](https://img.shields.io/badge/Go-1.26-blue?logo=go)](https://pkg.go.dev/github.com/tinybluerobots/issuebot)
44

55
Autonomous GitHub issue processor powered by any CLI tool. Watches repos for open issues, dispatches a command to resolve them, and pushes fixes or opens PRs.
66

77
## Install
88

9-
Download a prebuilt binary from the [latest release](https://github.com/tinybluerobots/cq/releases/latest).
9+
Download a prebuilt binary from the [latest release](https://github.com/tinybluerobots/issuebot/releases/latest).
1010

1111
Or via `go install`:
1212

1313
```bash
14-
go install github.com/tinybluerobots/cq@latest
14+
go install github.com/tinybluerobots/issuebot@latest
1515
```
1616

1717
Or build from source:
1818

1919
```bash
20-
git clone https://github.com/tinybluerobots/cq.git
21-
cd cq
22-
go build -o cq .
20+
git clone https://github.com/tinybluerobots/issuebot.git
21+
cd issuebot
22+
go build -o issuebot .
2323
```
2424

2525
## Usage
2626

2727
```bash
2828
# Watch current directory's repo with Claude
29-
cq --command "claude -p {prompt} --dangerously-skip-permissions"
29+
issuebot --command "claude -p {prompt} --dangerously-skip-permissions"
3030

3131
# Work directly in current directory (no clone)
32-
cq --local --command "claude -p {prompt} --dangerously-skip-permissions"
32+
issuebot --local --command "claude -p {prompt} --dangerously-skip-permissions"
3333

3434
# Watch a single repo with Copilot
35-
cq --repo owner/repo --command "copilot -p {prompt} --yolo"
35+
issuebot --repo owner/repo --command "copilot -p {prompt} --yolo"
3636

3737
# Watch all repos in an org with Gemini
38-
cq --org myorg --command "gemini -p {prompt} --yolo"
38+
issuebot --org myorg --command "gemini -p {prompt} --yolo"
3939

40-
# Only process issues labelled "cq"
41-
cq --repo owner/repo --label cq --command "claude -p {prompt} --dangerously-skip-permissions"
40+
# Only process issues labelled "bug"
41+
issuebot --repo owner/repo --label bug --command "claude -p {prompt} --dangerously-skip-permissions"
4242

4343
# Preview what the command would do without pushing
44-
cq --repo owner/repo --dry-run --command "claude -p {prompt} --dangerously-skip-permissions"
44+
issuebot --repo owner/repo --dry-run --command "claude -p {prompt} --dangerously-skip-permissions"
4545

4646
# Push fixes directly instead of opening PRs
47-
cq --repo owner/repo --strategy commit --command "copilot -p {prompt} --yolo"
47+
issuebot --repo owner/repo --strategy commit --command "copilot -p {prompt} --yolo"
4848

4949
# Poll every 5 minutes with 10 workers
50-
cq --org myorg --interval 5m --workers 10 --command "gemini -p {prompt} --yolo"
50+
issuebot --org myorg --interval 5m --workers 10 --command "gemini -p {prompt} --yolo"
5151

5252
# Get notified on failures via ntfy.sh
53-
cq --repo owner/repo --ntfy-topic my-alerts --command "copilot -p {prompt} --yolo"
53+
issuebot --repo owner/repo --ntfy-topic my-alerts --command "copilot -p {prompt} --yolo"
5454

5555
# Log to a file for background operation
56-
cq --org myorg --log-file ~/.cq/cq.log --command "claude -p {prompt} --dangerously-skip-permissions"
56+
issuebot --org myorg --log-file ~/.issuebot/issuebot.log --command "claude -p {prompt} --dangerously-skip-permissions"
5757

5858
# Use any command that reads from stdin
59-
cq --local --command "./my-issue-handler.sh"
59+
issuebot --local --command "./my-issue-handler.sh"
6060
```
6161

6262
### Flags
@@ -69,10 +69,10 @@ cq --local --command "./my-issue-handler.sh"
6969
| `--strategy` | `pr` | Git strategy: `pr` (branch + PR) or `commit` (push to default branch) |
7070
| `--interval` | `30s` | Polling interval |
7171
| `--workers` | `5` | Max concurrent repo workers |
72-
| `--workspace` | `~/.cq/repos` | Directory for cloned repos |
72+
| `--workspace` | `~/.issuebot/repos` | Directory for cloned repos |
7373
| `--local` | `false` | Use current directory instead of cloning |
7474
| `--command` | **(required)** | Command to run (prompt via stdin or `{prompt}` placeholder) |
75-
| `--prompt-file` | `~/.cq/prompt.tmpl` | Path to prompt template file |
75+
| `--prompt-file` | `~/.issuebot/prompt.tmpl` | Path to prompt template file |
7676
| `--dry-run` | `false` | Run command but skip push/PR (print diff instead) |
7777
| `--max-retries` | `3` | Max retry attempts per issue |
7878
| `--log-file` | | Log file path (defaults to stdout) |
@@ -86,15 +86,15 @@ Requires a GitHub token. Set `GITHUB_TOKEN` or run `gh auth login`.
8686

8787
1. **Polls** GitHub API for open issues (optionally filtered by label)
8888
2. **Clones** the repo (or uses current dir with `--local`)
89-
3. **Dispatches** a command (default: Claude CLI) with the issue as a prompt
89+
3. **Dispatches** the configured command with the issue as a prompt
9090
4. **Opens a PR** or pushes directly, depending on strategy
91-
5. **Tracks state** in `~/.cq/state.json` to avoid re-processing
91+
5. **Tracks state** in `~/.issuebot/state.json` to avoid re-processing
9292

9393
Each repo gets at most one concurrent worker to prevent conflicts. Failed issues are retried up to `--max-retries` times.
9494

9595
## Prompt Template
9696

97-
On first run, cq writes a default prompt template to `~/.cq/prompt.tmpl`. Edit it to customise how issues are presented to your command. Available template fields:
97+
On first run, issuebot writes a default prompt template to `~/.issuebot/prompt.tmpl`. Edit it to customise how issues are presented to your command. Available template fields:
9898

9999
| Field | Description |
100100
|-------|-------------|
@@ -112,24 +112,24 @@ The `--command` flag is required. By default, the prompt is passed via stdin. If
112112

113113
```bash
114114
# Claude Code
115-
cq --command "claude -p {prompt} --dangerously-skip-permissions"
115+
issuebot --command "claude -p {prompt} --dangerously-skip-permissions"
116116

117117
# GitHub Copilot
118-
cq --command "copilot -p {prompt} --yolo"
118+
issuebot --command "copilot -p {prompt} --yolo"
119119

120120
# Google Gemini CLI
121-
cq --command "gemini -p {prompt} --yolo"
121+
issuebot --command "gemini -p {prompt} --yolo"
122122

123123
# Any tool that reads stdin
124-
cq --command "./my-issue-handler.sh"
124+
issuebot --command "./my-issue-handler.sh"
125125
```
126126

127127
## Per-Issue Configuration
128128

129129
Override defaults per issue by adding a config block to the issue body:
130130

131131
```markdown
132-
<!-- cq
132+
<!-- issuebot
133133
strategy: commit
134134
branch: custom-branch-name
135135
-->
@@ -138,7 +138,7 @@ branch: custom-branch-name
138138
Example with post-command to request review after PR creation:
139139

140140
```markdown
141-
<!-- cq
141+
<!-- issuebot
142142
strategy: pr
143143
post-command: gh pr edit $PR_NUMBER --add-reviewer octocat
144144
-->
@@ -147,7 +147,7 @@ post-command: gh pr edit $PR_NUMBER --add-reviewer octocat
147147
| Key | Values | Description |
148148
|-----|--------|-------------|
149149
| `strategy` | `pr`, `commit` | Override the default git strategy |
150-
| `branch` | any string | Custom branch name (default: `cq/issue-{N}`) |
150+
| `branch` | any string | Custom branch name (default: `issuebot/issue-{N}`) |
151151
| `post-command` | any command | Shell command to run after PR creation (`$PR_URL` and `$PR_NUMBER` available) |
152152

153153
## Development

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
var Version = "dev"
1212

1313
var rootCmd = &cobra.Command{
14-
Use: "cq",
14+
Use: "issuebot",
1515
Short: "Autonomous GitHub issue processor powered by any CLI tool",
1616
Version: Version,
1717
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},

cmd/watch.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import (
1414

1515
"github.com/google/go-github/v69/github"
1616
"github.com/spf13/cobra"
17-
"github.com/tinybluerobots/cq/internal/config"
18-
"github.com/tinybluerobots/cq/internal/notify"
19-
"github.com/tinybluerobots/cq/internal/poller"
20-
"github.com/tinybluerobots/cq/internal/prompt"
21-
"github.com/tinybluerobots/cq/internal/state"
22-
"github.com/tinybluerobots/cq/internal/worker"
17+
"github.com/tinybluerobots/issuebot/internal/config"
18+
"github.com/tinybluerobots/issuebot/internal/notify"
19+
"github.com/tinybluerobots/issuebot/internal/poller"
20+
"github.com/tinybluerobots/issuebot/internal/prompt"
21+
"github.com/tinybluerobots/issuebot/internal/state"
22+
"github.com/tinybluerobots/issuebot/internal/worker"
2323
"golang.org/x/oauth2"
2424
)
2525

@@ -113,7 +113,7 @@ func runWatch(cmd *cobra.Command, args []string) error {
113113
// State
114114
home, _ := os.UserHomeDir()
115115

116-
stateDir := home + "/.cq"
116+
stateDir := home + "/.issuebot"
117117
if err := os.MkdirAll(stateDir, 0755); err != nil {
118118
return fmt.Errorf("mkdir state dir: %w", err)
119119
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/tinybluerobots/cq
1+
module github.com/tinybluerobots/issuebot
22

33
go 1.26
44

internal/config/config.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type IssueConfig struct {
3636
PostCommand string `yaml:"post-command"`
3737
}
3838

39-
var issueConfigRe = regexp.MustCompile(`(?s)<!--\s*cq\s*\n(.*?)\n-->`)
39+
var issueConfigRe = regexp.MustCompile(`(?s)<!--\s*issuebot\s*\n(.*?)\n-->`)
4040

4141
// DefaultCLIConfig returns a CLIConfig with sensible defaults.
4242
func DefaultCLIConfig() CLIConfig {
@@ -52,7 +52,7 @@ func DefaultCLIConfig() CLIConfig {
5252
}
5353

5454
// ParseIssueConfig extracts an IssueConfig from an issue body.
55-
// It looks for a <!-- cq ... --> HTML comment block containing YAML.
55+
// It looks for a <!-- issuebot ... --> HTML comment block containing YAML.
5656
func ParseIssueConfig(body string) IssueConfig {
5757
var cfg IssueConfig
5858

@@ -77,29 +77,29 @@ func ResolveStrategy(cli CLIConfig, issue IssueConfig) string {
7777
return cli.Strategy
7878
}
7979

80-
// ResolveBranch returns the issue-level branch if set, otherwise cq/issue-{N}.
80+
// ResolveBranch returns the issue-level branch if set, otherwise issuebot/issue-{N}.
8181
func ResolveBranch(issue IssueConfig, issueNumber int) string {
8282
if issue.Branch != "" {
8383
return issue.Branch
8484
}
8585

86-
return "cq/issue-" + strconv.Itoa(issueNumber)
86+
return "issuebot/issue-" + strconv.Itoa(issueNumber)
8787
}
8888

8989
func defaultWorkspace() string {
9090
home, err := os.UserHomeDir()
9191
if err != nil {
92-
return ".cq/repos"
92+
return ".issuebot/repos"
9393
}
9494

95-
return filepath.Join(home, ".cq", "repos")
95+
return filepath.Join(home, ".issuebot", "repos")
9696
}
9797

9898
func defaultPromptFile() string {
9999
home, err := os.UserHomeDir()
100100
if err != nil {
101-
return ".cq/prompt.tmpl"
101+
return ".issuebot/prompt.tmpl"
102102
}
103103

104-
return filepath.Join(home, ".cq", "prompt.tmpl")
104+
return filepath.Join(home, ".issuebot", "prompt.tmpl")
105105
}

internal/config/config_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
func TestParseIssueConfig_Full(t *testing.T) {
1212
body := `Some issue text here.
1313
14-
<!-- cq
14+
<!-- issuebot
1515
strategy: commit
1616
branch: my-feature
1717
-->
@@ -42,7 +42,7 @@ func TestParseIssueConfig_Empty(t *testing.T) {
4242
}
4343

4444
func TestParseIssueConfig_PartialFields(t *testing.T) {
45-
body := `<!-- cq
45+
body := `<!-- issuebot
4646
strategy: worktree
4747
-->`
4848

@@ -57,7 +57,7 @@ strategy: worktree
5757
}
5858

5959
func TestParseIssueConfig_UnknownKeysIgnored(t *testing.T) {
60-
body := `<!-- cq
60+
body := `<!-- issuebot
6161
strategy: pr
6262
branch: fix-123
6363
unknown_key: some_value
@@ -87,7 +87,7 @@ func TestDefaultConfig(t *testing.T) {
8787
{"workers", cfg.Workers, 5},
8888
{"max-retries", cfg.MaxRetries, 3},
8989
{"label", cfg.Label, ""},
90-
{"workspace-has-cq", strings.Contains(cfg.Workspace, ".cq/repos"), true},
90+
{"workspace-has-issuebot", strings.Contains(cfg.Workspace, ".issuebot/repos"), true},
9191
{"workspace-no-tilde", strings.HasPrefix(cfg.Workspace, "~"), false},
9292
}
9393

@@ -101,7 +101,7 @@ func TestDefaultConfig(t *testing.T) {
101101
}
102102

103103
func TestParseIssueConfig_MalformedYAML(t *testing.T) {
104-
body := `<!-- cq
104+
body := `<!-- issuebot
105105
strategy: [broken
106106
-->`
107107

@@ -115,7 +115,7 @@ func TestDefaultConfig_WorkspaceUsesHomeDir(t *testing.T) {
115115
cfg := DefaultCLIConfig()
116116
home, _ := os.UserHomeDir()
117117

118-
expected := filepath.Join(home, ".cq", "repos")
118+
expected := filepath.Join(home, ".issuebot", "repos")
119119
if cfg.Workspace != expected {
120120
t.Errorf("workspace: got %q, want %q", cfg.Workspace, expected)
121121
}
@@ -148,13 +148,13 @@ func TestResolveBranch_IssueOverrides(t *testing.T) {
148148

149149
func TestResolveBranch_Default(t *testing.T) {
150150
issue := IssueConfig{}
151-
if got := ResolveBranch(issue, 42); got != "cq/issue-42" {
152-
t.Errorf("got %q, want %q", got, "cq/issue-42")
151+
if got := ResolveBranch(issue, 42); got != "issuebot/issue-42" {
152+
t.Errorf("got %q, want %q", got, "issuebot/issue-42")
153153
}
154154
}
155155

156156
func TestParseIssueConfig_PostCommand(t *testing.T) {
157-
body := "<!-- cq\npost-command: gh pr comment $PR_NUMBER -b 'ready'\n-->"
157+
body := "<!-- issuebot\npost-command: gh pr comment $PR_NUMBER -b 'ready'\n-->"
158158
cfg := ParseIssueConfig(body)
159159

160160
if cfg.PostCommand != "gh pr comment $PR_NUMBER -b 'ready'" {
@@ -163,7 +163,7 @@ func TestParseIssueConfig_PostCommand(t *testing.T) {
163163
}
164164

165165
func TestParseIssueConfig_PostCommandEmpty(t *testing.T) {
166-
body := "<!-- cq\nstrategy: pr\n-->"
166+
body := "<!-- issuebot\nstrategy: pr\n-->"
167167
cfg := ParseIssueConfig(body)
168168

169169
if cfg.PostCommand != "" {

internal/poller/poller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"strings"
88

99
"github.com/google/go-github/v69/github"
10-
"github.com/tinybluerobots/cq/internal/ratelimit"
10+
"github.com/tinybluerobots/issuebot/internal/ratelimit"
1111
)
1212

1313
// ErrInvalidRepoFormat is returned when a repo string is not in "owner/name" format.

0 commit comments

Comments
 (0)