@atollhq/skill-codex 0.4.1 → 0.4.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/README.md CHANGED
@@ -7,23 +7,24 @@ Gives your Codex agent the ability to manage tasks, goals, KPIs, initiatives, mi
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npx @atollhq/skill-codex --key sk_atoll_... --org your-org-id --project project-id --team team-id
10
+ npx @atollhq/skill-codex --profile agent-a --key sk_atoll_... --org your-org-id --project project-id --team team-id
11
11
  # or
12
12
  ATOLL_API_KEY=sk_atoll_... ATOLL_ORG_ID=your-org-id npx @atollhq/skill-codex
13
13
  ```
14
14
 
15
- Optional defaults: `--project`, `--team`, and `--base-url` write `ATOLL_PROJECT`, `ATOLL_TEAM`, and `ATOLL_BASE_URL` for the agent.
15
+ Optional defaults: `--project`, `--team`, and `--base-url` are stored with the selected mode. Use `--no-project`, `--no-team`, or `--no-base-url` to clear previously saved defaults. When `--profile` is set, credentials and defaults are stored only in that named Atoll CLI profile. The installer does not write global `ATOLL_*` exports to `~/.zshrc` or `~/.bashrc`. Use `atoll --profile agent-a ...` for profile-scoped commands, or omit `--profile` to use env-var mode.
16
16
 
17
17
  Get an API key from **Settings > Members > Add Agent** (or **Create API Key** for integrations) in the Atoll app.
18
18
 
19
- This does four things:
19
+ This does five things:
20
20
 
21
21
  1. Installs the `atoll-api` skill to `~/.codex/skills/atoll-api/`
22
22
  2. Appends (or updates) an `# Atoll Integration` section in `~/.codex/AGENTS.md`
23
23
  3. Copies API reference files to `~/.codex/atoll-references/`
24
- 4. Appends Atoll env var exports to your shell profile (`~/.zshrc` or `~/.bashrc`)
24
+ 4. Creates or updates the named Atoll CLI profile when `--profile` is provided
25
+ 5. Appends Atoll env var exports to your shell profile (`~/.zshrc` or `~/.bashrc`) only when no profile is provided
25
26
 
26
- Open a fresh shell (or `source` your profile) and Codex has the Atoll integration.
27
+ For profile mode, Codex has the Atoll skill immediately and terminal commands can use `atoll --profile agent-a ...`. For env-var mode, open a fresh shell or `source` your profile.
27
28
 
28
29
  ## Using the integration
29
30
 
@@ -44,6 +45,7 @@ For terminal-first work, see [`@atollhq/cli`](https://www.npmjs.com/package/@ato
44
45
  ```bash
45
46
  npm install -g @atollhq/cli
46
47
  atoll auth login --profile agent-a --key sk_atoll_... --org-id org-uuid --project project-id --team team-id
48
+ atoll auth login --profile agent-a --key sk_atoll_... --org-id org-uuid --project project-id --no-team --no-base-url
47
49
  atoll heartbeat
48
50
  atoll issue list --json
49
51
  atoll agent-context
package/bin/install.mjs CHANGED
@@ -10,11 +10,15 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
10
10
  function parseArgs(argv) {
11
11
  const args = {}
12
12
  for (let i = 2; i < argv.length; i++) {
13
- if (argv[i] === '--key' && argv[i + 1]) args.key = argv[++i]
13
+ if (argv[i] === '--profile' && argv[i + 1]) args.profile = argv[++i]
14
+ else if (argv[i] === '--key' && argv[i + 1]) args.key = argv[++i]
14
15
  else if (argv[i] === '--org' && argv[i + 1]) args.org = argv[++i]
15
16
  else if (argv[i] === '--project' && argv[i + 1]) args.project = argv[++i]
17
+ else if (argv[i] === '--no-project') args.clearProject = true
16
18
  else if (argv[i] === '--team' && argv[i + 1]) args.team = argv[++i]
19
+ else if (argv[i] === '--no-team') args.clearTeam = true
17
20
  else if (argv[i] === '--base-url' && argv[i + 1]) args.baseUrl = argv[++i]
21
+ else if (argv[i] === '--no-base-url') args.clearBaseUrl = true
18
22
  else if (argv[i] === '--help' || argv[i] === '-h') args.help = true
19
23
  }
20
24
  return args
@@ -22,30 +26,38 @@ function parseArgs(argv) {
22
26
 
23
27
  function printUsage() {
24
28
  console.log(`
25
- Usage: npx @atollhq/skill-codex --key <api-key> --org <org-id> [--project <id>] [--team <id-or-slug>] [--base-url <url>]
29
+ Usage: npx @atollhq/skill-codex [--profile <name>] --key <api-key> --org <org-id> [--project <id>] [--team <id-or-slug>] [--base-url <url>]
26
30
  or: ATOLL_API_KEY=<api-key> ATOLL_ORG_ID=<org-id> npx @atollhq/skill-codex
27
31
 
28
32
  Options:
33
+ --profile Atoll CLI profile name to create/update. Profile mode does not write shell env vars.
29
34
  --key Atoll API key (sk_atoll_...). Defaults to ATOLL_API_KEY.
30
35
  --org Organization ID. Defaults to ATOLL_ORG_ID.
31
36
  --project Default project ID. Defaults to ATOLL_PROJECT.
37
+ --no-project Clear any saved default project.
32
38
  --team Default team ID or slug. Defaults to ATOLL_TEAM.
39
+ --no-team Clear any saved default team.
33
40
  --base-url Atoll base URL. Defaults to ATOLL_BASE_URL.
41
+ --no-base-url Clear any saved custom base URL.
34
42
  --help Show this help message
35
43
 
36
44
  Installs the Atoll integration for Codex CLI:
37
45
  - Installs the atoll-api skill to ~/.codex/skills/atoll-api/
38
46
  - Writes AGENTS.md with API reference to ~/.codex/
39
- - Sets Atoll env vars
47
+ - Creates/updates an Atoll CLI profile when --profile is provided
48
+ - Otherwise writes Atoll env vars to your shell profile for env-var mode
40
49
  `)
41
50
  }
42
51
 
43
52
  const args = parseArgs(process.argv)
44
53
  args.key ??= process.env.ATOLL_API_KEY
45
54
  args.org ??= process.env.ATOLL_ORG_ID
46
- args.project ??= process.env.ATOLL_PROJECT
47
- args.team ??= process.env.ATOLL_TEAM
48
- args.baseUrl ??= process.env.ATOLL_BASE_URL
55
+ if (args.clearProject) delete args.project
56
+ else args.project ??= process.env.ATOLL_PROJECT
57
+ if (args.clearTeam) delete args.team
58
+ else args.team ??= process.env.ATOLL_TEAM
59
+ if (args.clearBaseUrl) delete args.baseUrl
60
+ else args.baseUrl ??= process.env.ATOLL_BASE_URL
49
61
 
50
62
  if (args.help) { printUsage(); process.exit(0) }
51
63
 
@@ -60,6 +72,43 @@ if (!args.key.startsWith('sk_atoll_')) {
60
72
  process.exit(1)
61
73
  }
62
74
 
75
+ function readJson(path) {
76
+ if (!existsSync(path)) return {}
77
+ try {
78
+ return JSON.parse(readFileSync(path, 'utf-8'))
79
+ } catch {
80
+ console.error(`Warning: could not parse ${path}, creating fresh config`)
81
+ return {}
82
+ }
83
+ }
84
+
85
+ function writeAtollProfile() {
86
+ if (!args.profile) return null
87
+
88
+ const atollDir = join(homedir(), '.atoll')
89
+ const configPath = join(atollDir, 'config.json')
90
+ const config = readJson(configPath)
91
+ config.profiles ??= {}
92
+ config.profiles[args.profile] ??= {}
93
+ const profile = config.profiles[args.profile]
94
+
95
+ profile.apiKey = args.key
96
+ profile.orgId = args.org
97
+ delete profile.orgSlug
98
+ if (args.project) profile.defaultProject = args.project
99
+ else delete profile.defaultProject
100
+ if (args.team) profile.defaultTeam = args.team
101
+ else delete profile.defaultTeam
102
+ if (args.baseUrl) profile.baseUrl = args.baseUrl
103
+ else delete profile.baseUrl
104
+ config.activeProfile = args.profile
105
+
106
+ mkdirSync(atollDir, { recursive: true })
107
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n')
108
+ console.log(`Configured Atoll CLI profile "${args.profile}" in ${configPath}`)
109
+ return configPath
110
+ }
111
+
63
112
  // 1. Install the Codex skill to ~/.codex/skills/atoll-api/
64
113
  const codexDir = join(homedir(), '.codex')
65
114
  mkdirSync(codexDir, { recursive: true })
@@ -74,7 +123,13 @@ console.log(`Installed Atoll skill to ${skillDest}`)
74
123
  const skillMd = readFileSync(join(skillDir, 'SKILL.md'), 'utf-8')
75
124
  // Strip YAML frontmatter for AGENTS.md
76
125
  const body = skillMd.replace(/^---[\s\S]*?---\n*/, '')
126
+ const profileModeInstructions = args.profile ? `## Profile-scoped CLI configuration
127
+
128
+ This Codex install is scoped to Atoll CLI profile \`${args.profile}\`. No global \`ATOLL_API_KEY\`, \`ATOLL_ORG_ID\`, \`ATOLL_PROJECT\`, \`ATOLL_TEAM\`, or \`ATOLL_BASE_URL\` shell exports were written. Use \`atoll --profile ${args.profile} ...\` for direct Atoll CLI commands. Direct API snippets below use \`ATOLL_API_KEY\` / \`ATOLL_ORG_ID\` only when you intentionally choose env-var mode.
129
+
130
+ ` : ''
77
131
  const optionalCredentialLines = [
132
+ args.profile ? `- Atoll CLI profile: ${args.profile}` : null,
78
133
  args.project ? `- Default project ID: ${args.project}` : null,
79
134
  args.team ? `- Default team: ${args.team}` : null,
80
135
  args.baseUrl ? `- Base URL: ${args.baseUrl}` : null,
@@ -82,11 +137,12 @@ const optionalCredentialLines = [
82
137
 
83
138
  const agentsMd = `# Atoll Integration
84
139
 
140
+ ${profileModeInstructions}
85
141
  ${body}
86
142
 
87
143
  ## Credentials
88
144
 
89
- - API Key: set as ATOLL_API_KEY environment variable
145
+ - API Key: ${args.profile ? `stored in Atoll CLI profile \`${args.profile}\`` : 'set as ATOLL_API_KEY environment variable'}
90
146
  - Org ID: ${args.org}${optionalCredentialLines ? `\n${optionalCredentialLines}` : ''}
91
147
  `
92
148
 
@@ -114,7 +170,16 @@ for (const file of ['api-endpoints.md', 'api-fields.md']) {
114
170
  }
115
171
  console.log(`Copied API references to ${refsDir}`)
116
172
 
117
- // 4. Set env vars in shell profile
173
+ // 4. In profile mode, keep credentials scoped to the Atoll CLI profile.
174
+ if (args.profile) {
175
+ writeAtollProfile()
176
+ console.log('No Atoll shell exports were written.')
177
+ console.log(`Run profile-scoped commands with: atoll --profile ${args.profile} ...`)
178
+ console.log(`\nDone! Codex has the Atoll skill installed, and the Atoll CLI profile "${args.profile}" is active.`)
179
+ process.exit(0)
180
+ }
181
+
182
+ // 4. Set env vars in shell profile for env-var mode.
118
183
  const shell = process.env.SHELL || '/bin/bash'
119
184
  const profilePath = shell.includes('zsh')
120
185
  ? join(homedir(), '.zshrc')
@@ -127,18 +192,29 @@ function upsertExport(profile, name, value) {
127
192
  return `${profile.trimEnd()}\n${line}\n`
128
193
  }
129
194
 
195
+ function removeExport(profile, name) {
196
+ const pattern = new RegExp(`^export ${name}=.*\\n?`, 'm')
197
+ return profile.replace(pattern, '')
198
+ }
199
+
130
200
  if (existsSync(profilePath)) {
131
201
  let profile = readFileSync(profilePath, 'utf-8')
132
202
  if (!profile.includes('# Atoll (added by @atollhq/skill-codex)')) {
133
203
  profile = `${profile.trimEnd()}\n\n# Atoll (added by @atollhq/skill-codex)\n`
134
204
  }
205
+ profile = removeExport(profile, 'ATOLL_PROFILE')
135
206
  profile = upsertExport(profile, 'ATOLL_API_KEY', args.key)
136
207
  profile = upsertExport(profile, 'ATOLL_ORG_ID', args.org)
137
208
  if (args.project) profile = upsertExport(profile, 'ATOLL_PROJECT', args.project)
209
+ else profile = removeExport(profile, 'ATOLL_PROJECT')
138
210
  if (args.team) profile = upsertExport(profile, 'ATOLL_TEAM', args.team)
211
+ else profile = removeExport(profile, 'ATOLL_TEAM')
139
212
  if (args.baseUrl) profile = upsertExport(profile, 'ATOLL_BASE_URL', args.baseUrl)
213
+ else profile = removeExport(profile, 'ATOLL_BASE_URL')
140
214
  writeFileSync(profilePath, profile)
141
- const configuredVars = ['ATOLL_API_KEY', 'ATOLL_ORG_ID']
215
+
216
+ const configuredVars = []
217
+ configuredVars.push('ATOLL_API_KEY', 'ATOLL_ORG_ID')
142
218
  if (args.project) configuredVars.push('ATOLL_PROJECT')
143
219
  if (args.team) configuredVars.push('ATOLL_TEAM')
144
220
  if (args.baseUrl) configuredVars.push('ATOLL_BASE_URL')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atollhq/skill-codex",
3
- "version": "0.4.1",
3
+ "version": "0.4.4",
4
4
  "description": "Install the Atoll project management integration for Codex CLI",
5
5
  "bin": {
6
6
  "skill-codex": "bin/install.mjs"
package/skill/SKILL.md CHANGED
@@ -149,11 +149,23 @@ atoll feedback "The status error should list custom board statuses"
149
149
 
150
150
  # Projects & milestones
151
151
  atoll project list
152
+ atoll project delete <project-id> --confirm DELETE
152
153
  atoll milestone list --project <project-id>
153
154
  atoll milestone upsert --project <project-id> --name "v1.0" --date 2026-06-01
155
+
156
+ # Goals, KPIs, and initiatives
157
+ atoll goal create --title "Reach 100 paying customers by Q2" --target-date 2026-06-30
158
+ atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q2" --unit count --target 100 --current 34
159
+ atoll initiative create --title "Content pipeline" --goal "Reach 100 paying customers by Q2" --status active
160
+ atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 customers/mo"
161
+ atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --note "End-of-week Stripe check"
162
+
163
+ # Audit the strategy chain for gaps (orphaned initiatives, goals with no KPI, etc.)
164
+ atoll strategy audit
165
+ atoll strategy audit --severity critical --json
154
166
  ```
155
167
 
156
- Prefer the CLI for routine task operations, heartbeat checks, comments, and feedback. Use direct API calls when the CLI does not expose the needed endpoint yet.
168
+ Prefer the CLI for routine task operations, heartbeat checks, comments, feedback, and strategy setup. Use direct API calls when the CLI does not expose the needed endpoint yet.
157
169
 
158
170
  CLI JSON conventions:
159
171
 
@@ -163,6 +175,21 @@ CLI JSON conventions:
163
175
  - `atoll agent-context` returns a versioned command/flag manifest and available profile context.
164
176
  - `atoll plan validate/apply` consumes `schemaVersion: "atoll.plan.v1"` files with `milestones`, `issues`, `dependencies`, `initiativeLinks`, and `milestoneLinks`; local `key` values can be referenced by `milestoneKey`, `issueKey`, `dependsOn`, `blockedBy`, or `blocks`.
165
177
 
178
+ ## Remote MCP Server
179
+
180
+ Use `@atollhq/mcp-server` when an agent or ChatGPT-style client needs Atoll access but cannot run a local CLI command or read local auth profiles.
181
+
182
+ ```bash
183
+ npm install -g @atollhq/mcp-server
184
+ PORT=8787 atoll-mcp
185
+ ```
186
+
187
+ Remote MCP clients call `POST /mcp` with Streamable HTTP and should send `Authorization: Bearer sk_atoll_...` per request. Single-tenant deployments can set `ATOLL_API_KEY` and `ATOLL_ORG_ID` as environment variables.
188
+
189
+ The MCP server mirrors core CLI workflows with tools such as `atoll_get_heartbeat`, issue/project/goal/KPI/initiative/milestone tools, dependency tools, webhook tools, `atoll_send_feedback`, and `atoll_api_request` for advanced endpoints.
190
+
191
+ Keep Atoll skills separate from the MCP package. Skills are client-side agent guidance; the MCP server is runtime infrastructure for auth, transport, validation, and Atoll API calls.
192
+
166
193
  ## AI-Assisted Setup
167
194
 
168
195
  When a user needs help setting up Atoll, lean into the AI workflow. Atoll is most useful when the user's AI assistant helps turn messy context into projects, issues, goals, KPIs, and agent instructions.
@@ -177,6 +204,8 @@ atoll issue list --json --limit 10
177
204
 
178
205
  If the user is setting up Atoll in another AI tool, give them a copyable prompt. Keep secrets out of chat: tell the user to run auth commands locally and never ask them to paste `sk_atoll_...` keys into a model conversation unless they explicitly choose that risk.
179
206
 
207
+ If the user is in Atoll's first-run setup wizard, the key may be setup-scoped. In that mode, inspect the repo or interview the user, then create or revise the setup proposal only. Do not try to create projects, goals, KPIs, initiatives, or issues directly, and do not approve/apply the proposal. The human reviews the editable proposal in Atoll and approves it there.
208
+
180
209
  ### Prompt: Create the First Board
181
210
 
182
211
  ```text
@@ -299,8 +328,40 @@ atoll issue update ATOLL-42 --status done # complete
299
328
  5. `POST /api/orgs/{id}/initiatives/{id}/kpi-impacts` -- declare expected KPI impact
300
329
  6. Link issues and milestones to the initiative
301
330
 
331
+ CLI equivalent:
332
+
333
+ ```bash
334
+ atoll goal create --title "Reach 100 paying customers by Q2" --target-date 2026-06-30
335
+ atoll kpi create --name paying_customers --goal "Reach 100 paying customers by Q2" --unit count --target 100 --current 34
336
+ atoll initiative create --title "Content pipeline" --goal "Reach 100 paying customers by Q2" --status active
337
+ atoll initiative kpi link "Content pipeline" paying_customers --impact "+30 customers/mo"
338
+ atoll kpi snapshot add paying_customers --value 42 --initiative "Content pipeline" --note "End-of-week Stripe check"
339
+ ```
340
+
302
341
  Every KPI snapshot can be attributed to an initiative or issue, building a record of *what actually moved the numbers*.
303
342
 
343
+ ### Audit and improve the strategy
344
+
345
+ Use the audit to review the whole strategy chain at a high level and fix structural problems — the common one being initiatives created without a goal.
346
+
347
+ ```bash
348
+ atoll strategy audit # human-readable, grouped by severity
349
+ atoll strategy audit --json # findings[] for programmatic remediation
350
+ ```
351
+
352
+ `GET /api/orgs/{id}/strategy/audit` returns `findings[]` (each with a `type`, `severity`, the relevant entity id, and a concrete `suggested_fix`) plus `summary` counts. It diagnoses; you remediate with the normal write endpoints. Typical loop:
353
+
354
+ 1. `atoll strategy audit --json` to get findings.
355
+ 2. For each finding, apply its `suggested_fix`, e.g.:
356
+ - `initiative_orphaned` → `atoll initiative update "<initiative>" --goal "<goal>"` (or `PATCH .../initiatives/{id} { goal_id }`)
357
+ - `goal_missing_kpi` → `atoll kpi create --goal "<goal>" --name ... --target ...`
358
+ - `kpi_missing_target` → `atoll kpi update <kpi> --target ... --direction increase`
359
+ - `kpi_unrecorded` / `kpi_stale` → `atoll kpi snapshot add <kpi> --value ...`
360
+ - `initiative_missing_impact` → `atoll initiative kpi link "<initiative>" <kpi> --impact "..."`
361
+ 3. Re-run the audit to confirm the findings cleared.
362
+
363
+ This is the structural-health lens (is the strategy well-formed?), complementary to `heartbeat`, which is the operational lens (what should I do today?).
364
+
304
365
  ### Bulk create tasks from a plan
305
366
 
306
367
  `POST /api/orgs/{id}/issues/bulk` with `{ "issues": [{...}, ...] }` (max 50).
@@ -21,6 +21,7 @@ All endpoints require `Authorization: Bearer sk_atoll_...` header.
21
21
  - [KPIs](#kpis)
22
22
  - [Initiatives](#initiatives)
23
23
  - [Initiative Links](#initiative-links)
24
+ - [Strategy](#strategy)
24
25
  - [Heartbeat](#heartbeat)
25
26
  - [Activity](#activity)
26
27
  - [Teams](#teams)
@@ -63,7 +64,7 @@ All endpoints require `Authorization: Bearer sk_atoll_...` header.
63
64
  | POST | `/api/orgs/{id}/projects` | Create project (`{ name, description?, visibility?, color?, icon?, github_repo? }`) |
64
65
  | GET | `/api/orgs/{id}/projects/{projectId}` | Get project with issues |
65
66
  | PATCH | `/api/orgs/{id}/projects/{projectId}` | Update project (`{ name?, description?, status?, visibility?, color?, icon? }`) |
66
- | DELETE | `/api/orgs/{id}/projects/{projectId}` | Delete project (owner/admin) |
67
+ | DELETE | `/api/orgs/{id}/projects/{projectId}` | Permanently delete project and all tasks in it (owner/admin; body must include `{ "confirmation": "DELETE" }`) |
67
68
 
68
69
  Guest users only see projects they are assigned to.
69
70
 
@@ -109,6 +110,11 @@ Plan limits are enforced when creating projects, human members, agents/integrati
109
110
  | DELETE | `/api/orgs/{id}/issues/{issueId}` | Delete task (admin/owner only) |
110
111
  | POST | `/api/orgs/{id}/issues/bulk` | Bulk create tasks (up to 50) |
111
112
  | GET | `/api/orgs/{id}/issues/search?q=...` | Search tasks by title |
113
+ | GET | `/api/orgs/{id}/issues/{issueId}/initiatives` | List initiatives linked to a task |
114
+ | POST | `/api/orgs/{id}/issues/{issueId}/initiatives` | Link task to initiative (`{ initiative_id }`) |
115
+ | DELETE | `/api/orgs/{id}/issues/{issueId}/initiatives/{initiativeId}` | Unlink task from initiative |
116
+
117
+ Issue-centric initiative links follow task project permissions: reading links requires access to the task's project; linking and unlinking requires a non-guest member with non-view access.
112
118
 
113
119
  **List filters** (query params):
114
120
  - `status` -- `backlog`, `todo`, `in_progress`, `done`, `cancelled`
@@ -224,6 +230,14 @@ Create accepts `title` or legacy `name`, plus camelCase aliases `goalId`, `owner
224
230
  | POST | `.../initiatives/{id}/milestones` | Link milestone (`{ milestone_id }`) |
225
231
  | DELETE | `.../initiatives/{id}/milestones/{milestoneId}` | Unlink milestone |
226
232
 
233
+ ## Strategy
234
+
235
+ | Method | Endpoint | Description |
236
+ |--------|----------|-------------|
237
+ | GET | `/api/orgs/{id}/strategy/audit` | Audit the strategy chain for structural gaps + health issues, each with a suggested fix |
238
+
239
+ Returns findings only (not the full graph). Use it for a high-level review — orphaned initiatives/KPIs (no goal), goals with no KPI or no initiative, KPIs missing targets/stale/off-pace, initiatives missing impact/execution or stalled, blocked/overdue work — then remediate with the goal/KPI/initiative write endpoints above. Forbidden for guests. CLI: `atoll strategy audit [--severity critical|warning|info] [--json]`.
240
+
227
241
  ## Heartbeat
228
242
 
229
243
  | Method | Endpoint | Description |
@@ -333,7 +347,7 @@ Custom statuses per project. Each column defines a valid status value.
333
347
  | GET | `/api/orgs/{id}/issues/{issueId}/pr-links` | List linked pull requests |
334
348
  | POST | `/api/orgs/{id}/issues/{issueId}/pr-links` | Attach a GitHub PR URL (`{ url }`) |
335
349
 
336
- Attach PRs manually with a canonical GitHub pull request URL such as `https://github.com/owner/repo/pull/123`; malformed or non-PR URLs return `400`. PR links can also be created automatically via the GitHub webhook integration.
350
+ Attach PRs manually with a canonical GitHub pull request URL such as `https://github.com/owner/repo/pull/123`; malformed or non-PR URLs return `400`. On attach, Atoll refreshes GitHub metadata when available so title/status/head SHA reflect the PR instead of only the submitted URL. PR links can also be created or refreshed automatically via the GitHub webhook integration.
337
351
 
338
352
  ## Project Status Updates
339
353
 
@@ -398,7 +412,7 @@ URL must be HTTPS. Returns webhook record plus `secret` for HMAC verification.
398
412
  | Method | Endpoint | Description |
399
413
  |--------|----------|-------------|
400
414
  | GET | `/api/orgs/{id}/agents` | List agents (owner/admin) |
401
- | POST | `/api/orgs/{id}/agents` | Create agent (`{ name, role? }`) |
415
+ | POST | `/api/orgs/{id}/agents` | Create agent (`{ name, role?, setupScoped? }`) |
402
416
  | DELETE | `/api/orgs/{id}/agents/{agentId}` | Revoke agent |
403
417
  | GET | `/api/orgs/{id}/agents/{agentId}/keys` | List API keys |
404
418
  | POST | `/api/orgs/{id}/agents/{agentId}/keys` | Generate new key |
@@ -408,6 +422,22 @@ URL must be HTTPS. Returns webhook record plus `secret` for HMAC verification.
408
422
 
409
423
  Install snippets returns config for `claude-code`, `codex`, `gemini`, `openclaw` (agent prompt), `openclaw-manual`, `hermes` (agent prompt), and `hermes-manual`. The server resolves the org slug and validates optional project/team IDs before generating snippets.
410
424
 
425
+ ## Agent-first setup
426
+
427
+ | Method | Endpoint | Description |
428
+ |--------|----------|-------------|
429
+ | GET | `/api/orgs/{id}/setup` | Read latest setup session and active draft proposal (owner/admin) |
430
+ | POST | `/api/orgs/{id}/setup` | Create setup session (`{ preferredAi?, mode, setupAgentMemberId? }`) |
431
+ | PATCH | `/api/orgs/{id}/setup` | Skip setup (`{ setupSessionId, status: "skipped" }`) |
432
+ | POST | `/api/orgs/{id}/setup/proposals` | Setup-scoped local agent submits a draft proposal |
433
+ | PATCH | `/api/orgs/{id}/setup/proposals` | Owner/admin edits the active draft proposal |
434
+ | POST | `/api/orgs/{id}/setup/apply` | Owner/admin approves and applies a proposal |
435
+ | POST | `/api/orgs/{id}/setup/chatkit/session` | Create ChatKit client session for a web-agent setup session |
436
+ | POST | `/api/orgs/{id}/setup/chatkit/client-tool` | Browser-mediated ChatKit client tool endpoint for proposal submit/revise only |
437
+ | POST | `/api/orgs/{id}/setup/chatkit/tools` | Optional server-to-server ChatKit tool endpoint for proposal submit/revise only |
438
+
439
+ Setup-scoped agent keys can call setup proposal endpoints and auth validation, but not normal workspace mutation endpoints. Human approval applies proposals and promotes the setup key by clearing its setup scope. The default web-agent flow uses ChatKit client tools handled in the browser and posted to `client-tool` with the user's web session. ChatKit tools cannot apply proposals.
440
+
411
441
  ## Integrations
412
442
 
413
443
  | Method | Endpoint | Description |
@@ -10,6 +10,7 @@
10
10
  - [Automation Rule Fields](#automation-rule-fields)
11
11
  - [Custom View Fields](#custom-view-fields)
12
12
  - [Webhook Fields](#webhook-fields)
13
+ - [Setup Proposal Fields](#setup-proposal-fields)
13
14
  - [Heartbeat Response](#heartbeat-response)
14
15
  - [Analytics Response](#analytics-response)
15
16
  - [Plan Limit Errors](#plan-limit-errors)
@@ -183,6 +184,29 @@ Add/remove projects with `{ "project_id": "uuid" }`.
183
184
 
184
185
  URL must be HTTPS. Response includes `secret` for HMAC signature verification.
185
186
 
187
+ ## Setup Proposal Fields
188
+
189
+ First-run setup proposals are editable drafts. Setup-scoped local agents and ChatKit tools can submit or revise drafts; owner/admin humans apply them.
190
+
191
+ ```json
192
+ {
193
+ "setupSessionId": "setup-session-uuid",
194
+ "proposal": {
195
+ "projects": [{ "name": "Launch v1", "description": "..." }],
196
+ "goals": [{ "title": "Reach 100 paying customers", "target_date": "2026-06-30" }],
197
+ "kpis": [{ "name": "paying_customers", "target_value": 100, "target_direction": "increase" }],
198
+ "initiatives": [{ "title": "Content pipeline", "description": "Publish and distribute launch content", "expected_impact": "Increase qualified signups" }],
199
+ "milestones": [{ "name": "Public beta", "description": "Launch the public beta workspace", "due_date": "2026-05-15" }],
200
+ "issues": [{ "title": "Instrument signup funnel", "description": "Track signup start, completion, and activation", "priority": 1 }]
201
+ },
202
+ "evidence": {
203
+ "summary": "Optional notes about repo files or user answers that informed the proposal"
204
+ }
205
+ }
206
+ ```
207
+
208
+ Proposal JSON currently supports at most one item in each collection: `projects`, `goals`, `kpis`, `initiatives`, `milestones`, and `issues`. A revision replaces the active draft and preserves the previous revision as history. ChatKit tools and setup-scoped agents cannot apply proposals.
209
+
186
210
  ## Heartbeat Response
187
211
 
188
212
  ```json
@@ -218,6 +242,34 @@ URL must be HTTPS. Response includes `secret` for HMAC signature verification.
218
242
  }
219
243
  ```
220
244
 
245
+ ## Strategy Audit Response
246
+
247
+ `GET /api/orgs/{id}/strategy/audit` returns findings (sorted critical → warning → info), each with a concrete `suggested_fix`, plus summary counts.
248
+
249
+ ```json
250
+ {
251
+ "findings": [
252
+ {
253
+ "type": "initiative_orphaned",
254
+ "severity": "warning",
255
+ "title": "\"Content pipeline\" is not attached to a goal",
256
+ "message": "This initiative is not linked to any goal...",
257
+ "suggested_fix": "Attach it to a goal: PATCH /api/orgs/{orgId}/initiatives/<id> { \"goal_id\": \"<goalId>\" }",
258
+ "initiative_id": "..."
259
+ }
260
+ ],
261
+ "summary": { "total": 7, "critical": 1, "warning": 4, "info": 2 },
262
+ "counts_by_type": { "initiative_orphaned": 2, "goal_missing_kpi": 1 }
263
+ }
264
+ ```
265
+
266
+ Each finding carries whichever entity ids apply: `goal_id`, `kpi_id`, `initiative_id`, `issue_id`, `milestone_id`, `project_id`. Finding `type` values:
267
+
268
+ - Structural: `initiative_orphaned`, `kpi_orphaned`, `goal_missing_kpi`, `goal_missing_initiative`
269
+ - KPI health: `kpi_unrecorded`, `kpi_missing_target`, `kpi_stale`, `kpi_off_pace`
270
+ - Initiative health: `initiative_missing_impact`, `initiative_missing_execution`, `initiative_stalled`
271
+ - Execution: `issue_blocked`, `issue_overdue`, `milestone_overdue`
272
+
221
273
  ## Analytics Response
222
274
 
223
275
  ```json