acdev 1.0.2 → 1.0.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.
@@ -1,10 +1,16 @@
1
- # Optional. Prefer Claude Code subscription auth instead:
1
+ # Optional. GitHub CLI for issues/PRs — alternatives to interactive `gh auth login`:
2
+ # GH_TOKEN=ghp_your_personal_access_token
3
+ # GITHUB_TOKEN is also honored if GH_TOKEN is unset.
4
+ # SSH remotes can push/fetch git but do not authenticate gh for issues/PRs.
5
+ #
6
+ # Claude — prefer Claude Code subscription auth:
2
7
  # claude auth login
3
8
  # Or a long-lived subscription token:
4
9
  # claude setup-token
5
10
  # CLAUDE_CODE_OAUTH_TOKEN=...
6
11
  #
7
- # API Console billing (pay-as-you-go) — only if you have an Anthropic API key:
12
+ # API Console billing (pay-as-you-go) — only if you have an Anthropic API key.
13
+ # An API key takes precedence over subscription login:
8
14
  # ANTHROPIC_API_KEY=sk-ant-your-key-here
9
15
  #
10
16
  # Jira Cloud (only when ticketSource is "jira" in Settings / config.json):
package/README.md CHANGED
@@ -5,11 +5,13 @@ Local CLI + web UI for running AI coding agents on GitHub Issues or Jira tickets
5
5
  ## Prerequisites
6
6
 
7
7
  - Node.js 20+
8
- - [GitHub CLI](https://cli.github.com/) (`gh`) authenticated (`gh auth login`) — required for PRs (and for GitHub Issues when that is the ticket source)
9
- - Claude authentication (see [Authentication](#authentication) below)
8
+ - [GitHub CLI](https://cli.github.com/) (`gh`) on your `PATH` — required to fetch GitHub issues and open PRs. You can install `gh` first and authenticate later (see below).
10
9
  - A git repository with a `develop` branch on `origin` (or configure another base branch)
10
+ - Optional: Claude authentication for real agent runs (or use `--stub-agent` for UI-only testing)
11
11
  - Optional: Jira Cloud credentials when using Jira as the ticket source (see [Jira](#jira-ticket-source))
12
12
 
13
+ You do **not** need GitHub or Claude tokens before starting `acdev`. The server always starts (as long as you are inside a git repo); configure auth in **Settings → Authentication**, then enqueue jobs.
14
+
13
15
  ## Install
14
16
 
15
17
  ```bash
@@ -27,9 +29,27 @@ npm link # optional — makes `acdev` available globally
27
29
 
28
30
  ## Authentication
29
31
 
30
- `acdev` uses the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview), which shares credentials with [Claude Code](https://code.claude.com/docs/en/authentication). You need **one** of the following (`.env` is optional):
32
+ `acdev` starts even when auth is missing and prints a warning. Configure GitHub and Claude from **Settings → Authentication** in the web UI (tokens are written to `.acdev/.env`, gitignored) or by editing that file directly. Leave a Settings field blank to keep the current secret. Shell environment variables override `.env` on startup; saving in Settings updates the running process immediately so status refreshes without a restart.
33
+
34
+ Enqueueing issues, retrying jobs, and applying review feedback require Claude (unless `--stub-agent`). Opening a PR always requires GitHub auth. The Overview banner prompts you when auth is incomplete.
35
+
36
+ `.env` is optional when you already use `gh auth login` and `claude auth login` on the machine.
37
+
38
+ ### GitHub (issues / PRs)
39
+
40
+ `acdev` talks to GitHub through `gh`. **Any one** of these is enough:
41
+
42
+ 1. **Existing CLI login** — `gh auth login` (browser/device). Settings shows this as authenticated.
43
+ 2. **Personal access token** — paste a PAT in **Settings → GitHub / PR auth**, or set `GH_TOKEN` (or `GITHUB_TOKEN`) in `.acdev/.env`. `gh` reads those env vars, so no interactive login is required. Non-interactive CLI equivalent: `echo YOUR_PAT | gh auth login --with-token -h github.com`.
44
+ 3. **SSH remotes are not a substitute.** An SSH `origin` can push/fetch git, but it does **not** authenticate `gh` for issues or PRs. Settings may show the origin URL as read-only info.
31
45
 
32
- ### Option A Claude Pro / Max subscription (browser login)
46
+ On a fresh machine: install `gh`, start `acdev`, then paste a PAT in Settings (or set `GH_TOKEN` in `.acdev/.env`). You can also copy `.acdev/.env.example` to `.acdev/.env` before starting.
47
+
48
+ ### Claude
49
+
50
+ `acdev` uses the [Claude Agent SDK](https://platform.claude.com/docs/en/agent-sdk/overview), which shares credentials with [Claude Code](https://code.claude.com/docs/en/authentication). You need **one** of the following (API key wins if more than one is set):
51
+
52
+ #### Option A — Claude Pro / Max subscription (browser login)
33
53
 
34
54
  Best when you already pay for claude.ai and are not allowed to use API keys.
35
55
 
@@ -44,14 +64,18 @@ claude auth status
44
64
 
45
65
  3. Run `acdev` with **no** `ANTHROPIC_API_KEY` set (an API key would take precedence and bill the Console instead of your subscription)
46
66
 
67
+ Settings cannot complete browser OAuth — that still needs `claude auth login` on the host. Detected method in Settings: `claude-code-login`.
68
+
47
69
  For CI / non-interactive shells, generate a long-lived subscription token instead:
48
70
 
49
71
  ```bash
50
72
  claude setup-token
51
- export CLAUDE_CODE_OAUTH_TOKEN=... # or put it in `.acdev/.env`
73
+ export CLAUDE_CODE_OAUTH_TOKEN=... # or paste it in Settings → Claude authentication
52
74
  ```
53
75
 
54
- ### Option B — Anthropic API key (Console / pay-as-you-go)
76
+ #### Option B — Anthropic API key (Console / pay-as-you-go)
77
+
78
+ Paste the key in **Settings → Claude authentication**, or:
55
79
 
56
80
  ```bash
57
81
  cp .acdev/.env.example .acdev/.env
@@ -66,7 +90,7 @@ export ANTHROPIC_API_KEY=sk-ant-...
66
90
  acdev
67
91
  ```
68
92
 
69
- A Claude.ai browser-only subscription does **not** give you an API key. API keys come from the [Claude Console](https://platform.claude.com/) and are billed separately from Pro/Max.
93
+ A Claude.ai browser-only subscription does **not** give you an API key. API keys come from the [Claude Console](https://platform.claude.com/) and are billed separately from Pro/Max. To switch back to subscription login, clear the saved API key in Settings (or omit it from `.env`).
70
94
 
71
95
  ## Jira ticket source
72
96
 
@@ -101,13 +125,13 @@ Optional **Rules** in Settings can move the Jira ticket to a target status (e.g.
101
125
 
102
126
  ## Usage
103
127
 
104
- From inside a cloned git repository (after authenticating as above):
128
+ From inside a cloned git repository:
105
129
 
106
130
  ```bash
107
131
  acdev
108
132
  ```
109
133
 
110
- The tool starts a local server (default port `4848`), opens the browser, and shows the web UI.
134
+ The tool starts a local server (default port `4848`), opens the browser, and shows the web UI. If GitHub or Claude auth is missing, the CLI warns and the UI shows a banner — open **Settings → Authentication** to add tokens, then enqueue jobs.
111
135
 
112
136
  ### CLI flags
113
137
 
@@ -136,13 +160,13 @@ The tool starts a local server (default port `4848`), opens the browser, and sho
136
160
  | **Review** | Edit PR title/body, colored diff, approve draft or ready, reject, or Clear |
137
161
  | **Logs** | Cross-job activity log with job filter |
138
162
  | **Alerts** | Failures / warnings with Retry, Clear, and dismiss |
139
- | **Settings** | Ticket source (GitHub / Jira), Jira connection, post-PR rules, and `.acdev/config.json` fields |
163
+ | **Settings** | Ticket source (GitHub / Jira), GitHub + Claude authentication, Jira connection, post-PR rules, and `.acdev/config.json` fields |
140
164
 
141
- Model selection lives in the sidebar (and Settings). Default is **Sonnet 5** (`claude-sonnet-5`).
165
+ Model selection lives in **Settings → Configuration**. The sidebar shows the current model as a read-only label. Default is **Sonnet 5** (`claude-sonnet-5`).
142
166
 
143
167
  ## Configuration
144
168
 
145
- Optional secrets go in `.acdev/.env` (copy from `.acdev/.env.example`). The file is gitignored and not required when using `claude auth login` with GitHub Issues only.
169
+ Optional secrets go in `.acdev/.env` (copy from `.acdev/.env.example`), or paste them in **Settings**. The file is gitignored and not required when using `gh auth login` and `claude auth login` with GitHub Issues only.
146
170
 
147
171
  Prefer **Settings** in the web UI to change runtime config — values persist to `.acdev/config.json` and apply to the next job without restart. You can still edit the file by hand if you prefer.
148
172
 
@@ -160,26 +184,41 @@ On first run, creates `.acdev/config.json`:
160
184
  "jiraBaseUrl": "",
161
185
  "jiraPrLinkPhrase": "Relates to",
162
186
  "jiraRules": {
163
- "afterPrOpened": { "enabled": false, "targetStatus": "In Review" }
187
+ "afterPrOpened": {
188
+ "enabled": false,
189
+ "action": "none",
190
+ "targetStatus": "In Review",
191
+ "label": ""
192
+ }
164
193
  },
165
194
  "githubRules": {
166
- "afterPrOpened": { "enabled": false, "action": "none", "label": "" }
195
+ "afterPrOpened": {
196
+ "enabled": false,
197
+ "action": "none",
198
+ "targetStatus": "In Review",
199
+ "label": ""
200
+ }
167
201
  }
168
202
  }
169
203
  ```
170
204
 
171
- `jiraRules.afterPrOpened` transitions the issue to a workflow status whose name matches `targetStatus` (case-insensitive). `githubRules.afterPrOpened.action` is `none`, `add_label`, or `close_issue` (GitHub issues have no built-in board statuses; Projects API is not used).
205
+ `jiraRules.afterPrOpened` and `githubRules.afterPrOpened` share the same shape: `enabled`, `action` (`none` | `set_status` | `add_label` | `close_issue`), `targetStatus`, and `label`.
206
+
207
+ | Action | Jira | GitHub |
208
+ |--------|------|--------|
209
+ | `set_status` | Workflow transition to a status whose name matches `targetStatus` (case-insensitive) | Applies a label named after `targetStatus` via `gh issue edit --add-label` (Projects board API is not used) |
210
+ | `add_label` | Adds the Jira label via REST `update.labels` `{ add }` | Adds the issue label via `gh` |
211
+ | `close_issue` | Transitions to a Done-category status, or else a Done/Closed/Resolved-like name | Closes the GitHub issue |
172
212
 
173
- Supported `model` values (Claude Agent SDK):
213
+ Legacy Jira configs that only had `enabled` + `targetStatus` (no `action`) still work: when enabled, they migrate to `action: "set_status"`.
214
+ Supported `model` values are Claude Agent SDK / Claude Code model ids (aliases like `claude-sonnet-5` / `claude-opus-5` / `sonnet`, or Anthropic API model ids). The Settings dropdown is populated by `GET /api/models`:
174
215
 
175
- | UI label | Model ID |
176
- |----------|----------|
177
- | Sonnet 5 (default) | `claude-sonnet-5` |
178
- | Opus 5 | `claude-opus-5` |
216
+ 1. When `ANTHROPIC_API_KEY` (or `ANTHROPIC_AUTH_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN`) is set — or Claude Code browser login credentials are readable from the local store — acdev calls Anthropic’s Models API (`GET /v1/models`) and merges results with curated Claude Code aliases.
217
+ 2. Otherwise (or if the live fetch fails), the UI falls back to a curated list (Sonnet/Opus/Fable/Haiku generations + common Code aliases such as `sonnet` / `opus`) so the dropdown stays useful without an API key. The Settings hint notes when the list is static (`source: "fallback"`).
179
218
 
180
- Unknown or removed model IDs in an existing config are migrated to `claude-sonnet-5` on load.
219
+ Empty or malformed model IDs in an existing config are migrated to `claude-sonnet-5` on load. Other valid ids are kept as-is.
181
220
 
182
- Change via **Settings** / the sidebar model toggle (`PATCH /api/config`) or `--model`. Takes effect for the next agent run without restart.
221
+ Change via **Settings Configuration** (`PATCH /api/config`) or `--model`. Takes effect for the next agent run without restart.
183
222
 
184
223
  Job state is persisted in `.acdev/state.json`.
185
224
 
@@ -193,11 +232,13 @@ npm test
193
232
 
194
233
  ## Architecture
195
234
 
196
- - `bin/acdev.js` — CLI entry, startup checks (`gh` always; Jira not required at startup)
235
+ - `bin/acdev.js` — CLI entry; soft-checks `gh` / Claude auth (warns, does not exit). Tokens in `.acdev/.env` are loaded before auth checks. Job APIs reject until auth is OK.
197
236
  - `src/claude-auth.js` — Anthropic API key / Claude Code subscription auth detection
237
+ - `src/gh-auth.js` — GitHub CLI auth (`gh auth login` or `GH_TOKEN`)
198
238
  - `src/server.js` — Express API, SSE logs, job queue, config + Jira test endpoints
199
239
  - `src/git.js` — Worktree lifecycle (`issue-<id>` paths), `feat/`/`fix/` branch naming, diff, push
200
240
  - `src/agent.js` — Claude Agent SDK integration (`options.model`); GitHub vs Jira prompts
241
+ - `src/models.js` — `GET /api/models` list (Anthropic Models API + curated fallback)
201
242
  - `src/github.js` — Issue URL parsing, issue fetch via `gh`, `createPr({ draft })`
202
243
  - `src/jira.js` — Jira Cloud parse/fetch/test + issuetype → feat/fix
203
244
  - `src/config.js` — Load/save `.acdev/config.json` including ticket source
@@ -217,7 +258,8 @@ npm test
217
258
  | `POST` | `/api/jobs/:id/reject` | Discard worktree (keeps job as `discarded`) |
218
259
  | `DELETE` | `/api/jobs/:id` | Clear job from history (worktree best-effort); 409 if in-flight |
219
260
  | `POST` | `/api/jobs/:id/retry` | Re-queue failed/discarded |
220
- | `GET` | `/api/config` | Editable config + models + Jira status (token masked) |
261
+ | `GET` | `/api/config` | Editable config + curated models + Jira status (token masked) |
262
+ | `GET` | `/api/models` | `{ models, selected, source }` — live Anthropic list or curated fallback |
221
263
  | `PATCH` | `/api/config` | Partial update including `ticketSource`, `jiraBaseUrl`; `jiraEmail` / `jiraApiToken` → `.env` |
222
264
  | `POST` | `/api/jira/test` | Test Jira credentials (`GET /rest/api/3/myself`) |
223
265
 
package/bin/acdev.js CHANGED
@@ -3,8 +3,8 @@
3
3
  import { execSync } from 'node:child_process';
4
4
  import http from 'node:http';
5
5
  import open from 'open';
6
- import { checkClaudeAuth } from '../src/claude-auth.js';
7
- import { checkGhAuth } from '../src/gh-auth.js';
6
+ import { checkClaudeAuth, formatClaudeAuthError } from '../src/claude-auth.js';
7
+ import { checkGhAuth, formatGhAuthError } from '../src/gh-auth.js';
8
8
  import { loadConfig } from '../src/config.js';
9
9
  import { loadEnv } from '../src/env.js';
10
10
  import { migrateLegacyDataDir, migrateLegacyWorktreesDir } from '../src/paths.js';
@@ -58,38 +58,26 @@ async function main() {
58
58
  migrateLegacyWorktreesDir(repoRoot);
59
59
  loadEnv(repoRoot);
60
60
 
61
+ // Soft auth: always start the server so Settings can add tokens.
62
+ // Job endpoints reject with a clear 4xx until auth is configured.
61
63
  const ghAuth = checkGhAuth();
62
64
  if (!ghAuth.ok) {
63
- if (ghAuth.reason === 'not-found') {
64
- console.error(
65
- ' GitHub CLI (gh) not found in PATH. Install it from https://cli.github.com/'
66
- );
67
- } else {
68
- console.error(
69
- '✖ GitHub CLI not authenticated for github.com. Run `gh auth login -h github.com` first.'
70
- );
71
- }
72
- process.exit(1);
65
+ console.warn(formatGhAuthError(ghAuth).replace(/^✖/m, ''));
66
+ console.warn(
67
+ ' Continuing without GitHub auth configure in Settings Authentication, then enqueue jobs.'
68
+ );
73
69
  }
74
70
 
75
71
  if (!opts.stubAgent) {
76
72
  const claudeAuth = checkClaudeAuth();
77
73
  if (!claudeAuth.ok) {
78
- console.error(
79
- [
80
- ' No Anthropic / Claude Code authentication found.',
81
- '',
82
- 'Authenticate with one of:',
83
- ' 1. Claude Pro/Max subscription (browser): install Claude Code, then run',
84
- ' `claude auth login` (or `claude setup-token` and set CLAUDE_CODE_OAUTH_TOKEN)',
85
- ' 2. Anthropic API key (API billing): set ANTHROPIC_API_KEY in the environment',
86
- ' or in `.acdev/.env` (optional file; copy from `.acdev/.env.example`)',
87
- '',
88
- 'For UI-only testing without auth: pass `--stub-agent`.',
89
- ].join('\n')
74
+ console.warn(formatClaudeAuthError(claudeAuth).replace(/^✖/m, '⚠'));
75
+ console.warn(
76
+ ' Continuing without Claude auth configure in Settings → Authentication (or pass --stub-agent).'
90
77
  );
91
- process.exit(1);
92
78
  }
79
+ } else {
80
+ console.log('✓ Stub agent enabled (Claude auth not required)');
93
81
  }
94
82
 
95
83
  const config = loadConfig(repoRoot);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "acdev",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Local CLI + web UI for running AI agents on GitHub issues via git worktrees",
5
5
  "type": "module",
6
6
  "bin": {