@daemux/store-automator 0.5.1 → 0.5.3

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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "App Store & Google Play automation for Flutter apps",
8
- "version": "0.5.1"
8
+ "version": "0.5.3"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "store-automator",
13
13
  "source": "./plugins/store-automator",
14
14
  "description": "3 agents for app store publishing: reviewer, meta-creator, media-designer",
15
- "version": "0.5.1",
15
+ "version": "0.5.3",
16
16
  "keywords": ["flutter", "app-store", "google-play", "fastlane", "codemagic"]
17
17
  }
18
18
  ]
package/README.md CHANGED
@@ -27,8 +27,8 @@ npm install @daemux/store-automator
27
27
 
28
28
  The postinstall script will:
29
29
 
30
- 1. Prompt for MCP server tokens (Stitch, Cloudflare)
31
- 2. Configure `.mcp.json` with MCP servers (Playwright, mobile-mcp, Stitch, Cloudflare)
30
+ 1. Prompt for MCP server tokens (Stitch, Cloudflare, Codemagic)
31
+ 2. Configure `.mcp.json` with MCP servers (Playwright, mobile-mcp, Stitch, Cloudflare, Codemagic)
32
32
  3. Install the plugin marketplace and register agents
33
33
  4. Copy `CLAUDE.md` template to `.claude/CLAUDE.md`
34
34
  5. Copy CI/CD templates (Fastlane, scripts, web pages, ci.config.yaml)
@@ -112,8 +112,54 @@ The package configures these MCP servers in `.mcp.json`:
112
112
  |--------|---------|---------------|
113
113
  | playwright | Browser automation for testing web pages | None |
114
114
  | mobile-mcp | Mobile device automation | None |
115
- | stitch | AI design tool for screenshot generation | Google API Key |
116
- | cloudflare | Cloudflare Pages deployment | API Token + Account ID |
115
+ | stitch | AI design tool for screenshot generation | `STITCH_API_KEY` |
116
+ | cloudflare | Cloudflare Pages deployment | `CLOUDFLARE_API_TOKEN` + Account ID |
117
+ | codemagic | Codemagic CI/CD build management (27 tools) | `CODEMAGIC_API_TOKEN` |
118
+
119
+ ## Non-interactive Install
120
+
121
+ For CI/CD environments or scripted setups, pass tokens as CLI flags to skip interactive prompts:
122
+
123
+ ```bash
124
+ npx @daemux/store-automator \
125
+ --codemagic-token=YOUR_CM_TOKEN \
126
+ --stitch-key=YOUR_STITCH_KEY \
127
+ --cloudflare-token=YOUR_CF_TOKEN \
128
+ --cloudflare-account-id=YOUR_CF_ACCOUNT_ID
129
+ ```
130
+
131
+ Any tokens provided via flags will skip the corresponding interactive prompt. If all four tokens are provided, the entire interactive session is skipped.
132
+
133
+ ## CLI Options
134
+
135
+ ```
136
+ Usage: npx @daemux/store-automator [options]
137
+
138
+ Options:
139
+ -g, --global Install globally (~/.claude) instead of project scope
140
+ -u, --uninstall Uninstall plugin and remove files
141
+ --postinstall Run as postinstall hook (auto-detected)
142
+ -v, --version Show version number
143
+ -h, --help Show help
144
+
145
+ MCP Token Flags (skip interactive prompts):
146
+ --codemagic-token=TOKEN Codemagic API token
147
+ --stitch-key=KEY Stitch MCP API key
148
+ --cloudflare-token=TOKEN Cloudflare API token
149
+ --cloudflare-account-id=ID Cloudflare account ID
150
+
151
+ Codemagic:
152
+ --codemagic-setup Register repo and optionally trigger build
153
+ --token=TOKEN API token (or set CM_API_TOKEN env var)
154
+ --branch=BRANCH Branch to build (default: main)
155
+ --workflow=ID Workflow ID (default: default)
156
+ --trigger Trigger build after setup
157
+ --wait Wait for build completion (implies --trigger)
158
+
159
+ GitHub Actions:
160
+ --github-setup Set CM_API_TOKEN secret for GitHub Actions
161
+ --token=TOKEN API token (or set CM_API_TOKEN env var)
162
+ ```
117
163
 
118
164
  ## License
119
165
 
package/bin/cli.mjs CHANGED
@@ -21,19 +21,34 @@ let cmWorkflowId = 'default';
21
21
  let cmTrigger = false;
22
22
  let cmWait = false;
23
23
 
24
+ const cliTokens = {};
25
+
26
+ function flagValue(arg, prefix) {
27
+ return arg.startsWith(prefix) ? arg.slice(prefix.length) : undefined;
28
+ }
29
+
30
+ const tokenFlags = {
31
+ '--codemagic-token=': 'codemagicToken',
32
+ '--stitch-key=': 'stitchApiKey',
33
+ '--cloudflare-token=': 'cloudflareToken',
34
+ '--cloudflare-account-id=': 'cloudflareAccountId',
35
+ };
36
+
24
37
  for (const arg of args) {
25
- if (arg.startsWith('--token=')) {
26
- cmTokenArg = arg.slice(8);
27
- continue;
28
- }
29
- if (arg.startsWith('--branch=')) {
30
- cmBranch = arg.slice(9);
31
- continue;
32
- }
33
- if (arg.startsWith('--workflow=')) {
34
- cmWorkflowId = arg.slice(11);
35
- continue;
38
+ let v;
39
+ if ((v = flagValue(arg, '--token=')) !== undefined) { cmTokenArg = v; continue; }
40
+ if ((v = flagValue(arg, '--branch=')) !== undefined) { cmBranch = v; continue; }
41
+ if ((v = flagValue(arg, '--workflow=')) !== undefined) { cmWorkflowId = v; continue; }
42
+
43
+ let matched = false;
44
+ for (const [prefix, key] of Object.entries(tokenFlags)) {
45
+ if ((v = flagValue(arg, prefix)) !== undefined) {
46
+ cliTokens[key] = v;
47
+ matched = true;
48
+ break;
49
+ }
36
50
  }
51
+ if (matched) continue;
37
52
 
38
53
  switch (arg) {
39
54
  case '-g':
@@ -64,23 +79,29 @@ for (const arg of args) {
64
79
  console.log(`Usage: npx @daemux/store-automator [options]
65
80
 
66
81
  Options:
67
- -g, --global Install globally (~/.claude) instead of project scope
68
- -u, --uninstall Uninstall plugin and remove files
69
- --postinstall Run as postinstall hook (auto-detected)
70
- -v, --version Show version number
71
- -h, --help Show help
82
+ -g, --global Install globally (~/.claude) instead of project scope
83
+ -u, --uninstall Uninstall plugin and remove files
84
+ --postinstall Run as postinstall hook (auto-detected)
85
+ -v, --version Show version number
86
+ -h, --help Show help
87
+
88
+ MCP Token Flags (skip interactive prompts):
89
+ --codemagic-token=TOKEN Codemagic API token
90
+ --stitch-key=KEY Stitch MCP API key
91
+ --cloudflare-token=TOKEN Cloudflare API token
92
+ --cloudflare-account-id=ID Cloudflare account ID
72
93
 
73
94
  Codemagic:
74
- --codemagic-setup Register repo and optionally trigger build
75
- --token=TOKEN API token (or set CM_API_TOKEN env var)
76
- --branch=BRANCH Branch to build (default: main)
77
- --workflow=ID Workflow ID (default: default)
78
- --trigger Trigger build after setup
79
- --wait Wait for build completion (implies --trigger)
95
+ --codemagic-setup Register repo and optionally trigger build
96
+ --token=TOKEN API token (or set CM_API_TOKEN env var)
97
+ --branch=BRANCH Branch to build (default: main)
98
+ --workflow=ID Workflow ID (default: default)
99
+ --trigger Trigger build after setup
100
+ --wait Wait for build completion (implies --trigger)
80
101
 
81
102
  GitHub Actions (auto-configured during install if gh CLI available):
82
- --github-setup Set CM_API_TOKEN secret for GitHub Actions
83
- --token=TOKEN API token (or set CM_API_TOKEN env var)
103
+ --github-setup Set CM_API_TOKEN secret for GitHub Actions
104
+ --token=TOKEN API token (or set CM_API_TOKEN env var)
84
105
 
85
106
  Examples:
86
107
  npx @daemux/store-automator Install for project
@@ -89,7 +110,11 @@ Examples:
89
110
  npx @daemux/store-automator -g -u Uninstall globally
90
111
  npx @daemux/store-automator --codemagic-setup Register with Codemagic
91
112
  npx @daemux/store-automator --codemagic-setup --trigger --wait Trigger and wait
92
- npx @daemux/store-automator --github-setup Configure GitHub Actions`);
113
+ npx @daemux/store-automator --github-setup Configure GitHub Actions
114
+
115
+ Non-interactive install (CI/CD):
116
+ npx @daemux/store-automator --codemagic-token=TOKEN --stitch-key=KEY
117
+ npx @daemux/store-automator --cloudflare-token=TOKEN --cloudflare-account-id=ID`);
93
118
  process.exit(0);
94
119
  break; // eslint: no-fallthrough
95
120
  case '-v':
@@ -122,7 +147,7 @@ try {
122
147
  await runUninstall(scope);
123
148
  } else {
124
149
  const { runInstall } = await import('../src/install.mjs');
125
- await runInstall(scope, isPostinstall);
150
+ await runInstall(scope, isPostinstall, cliTokens);
126
151
  }
127
152
  } catch (err) {
128
153
  if (isPostinstall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daemux/store-automator",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Full App Store & Google Play automation for Flutter apps with Claude Code agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,38 +42,62 @@ The Codemagic pipeline runs two parallel workflows on push to `main`:
42
42
  **iOS Release**: Flutter analyze -> Flutter test -> Build IPA -> Code signing -> Upload metadata + screenshots -> Deploy to App Store Connect -> Sync IAP
43
43
  **Android Release**: Flutter analyze -> Flutter test -> Build AAB -> Keystore signing -> Check Google Play readiness -> Deploy to Google Play -> Sync IAP
44
44
 
45
+ ### Token Configuration
46
+
47
+ The Codemagic API token is auto-configured via the codemagic MCP server in `.mcp.json` (set during install). You do not need to resolve the token manually -- all MCP tool calls authenticate automatically. If the codemagic MCP server is missing from `.mcp.json`, instruct the user to re-run `npx @daemux/store-automator` or add `--codemagic-token=TOKEN` to configure it.
48
+
45
49
  ### Triggering Builds
46
50
 
47
- **Option 1: Git push** (preferred)
51
+ **Option 1: Git push** (preferred when webhooks are configured)
48
52
  ```bash
49
53
  git push origin main
50
54
  ```
51
55
  Codemagic triggers both iOS and Android workflows automatically on push to `main`.
52
56
 
53
- **Option 2: Codemagic REST API**
54
- ```bash
55
- # Requires CM_API_TOKEN environment variable
56
- # Uses src/codemagic-api.mjs functions: startBuild(token, appId, workflowId, branch)
57
- node -e "
58
- import {startBuild} from './src/codemagic-api.mjs';
59
- const r = await startBuild(process.env.CM_API_TOKEN, '<appId>', '<workflowId>', 'main');
60
- console.log(JSON.stringify(r, null, 2));
61
- "
62
- ```
57
+ **Option 2: Codemagic MCP** (preferred for full automation -- allows status polling and log reading)
58
+ Use the `start_build` MCP tool:
59
+ - `appId`: from `codemagic.app_id` in `ci.config.yaml`
60
+ - `workflowId`: from `codemagic.workflows` in `ci.config.yaml`
61
+ - `branch`: `main` (or as needed)
63
62
 
64
63
  ### Monitoring Build Status
65
64
 
66
- ```bash
67
- # Poll build status via API
68
- node -e "
69
- import {getBuildStatus} from './src/codemagic-api.mjs';
70
- const r = await getBuildStatus(process.env.CM_API_TOKEN, '<buildId>');
71
- console.log(JSON.stringify(r, null, 2));
72
- "
73
- ```
65
+ Use the `get_build` MCP tool with the `buildId` returned from `start_build`. Poll every 60 seconds until the build reaches a terminal state.
74
66
 
75
67
  Build states: `queued` -> `preparing` -> `building` -> `testing` -> `publishing` -> `finished` | `failed` | `canceled`
76
68
 
69
+ ### Available Codemagic MCP Tools
70
+
71
+ | Tool | Description |
72
+ |------|-------------|
73
+ | `list_apps` | List all Codemagic applications |
74
+ | `get_app` | Get details of a specific application |
75
+ | `add_app` | Add a new application to Codemagic |
76
+ | `start_build` | Start a new build |
77
+ | `get_build` | Get details of a specific build |
78
+ | `cancel_build` | Cancel a running build |
79
+ | `list_builds` | List builds for a team (V3 API) |
80
+ | `get_artifact_url` | Get the download URL for a build artifact |
81
+ | `create_public_artifact_url` | Create a time-limited public URL for an artifact |
82
+ | `list_caches` | List build caches for an application |
83
+ | `delete_caches` | Delete build caches for an application |
84
+ | `setup_asc_credentials` | Create variable group with App Store Connect credentials |
85
+ | `setup_code_signing` | Create variable group with iOS code signing cert and profile |
86
+ | `get_user` | Get the current authenticated user info |
87
+ | `list_teams` | List all teams the user belongs to |
88
+ | `get_team` | Get details of a specific team |
89
+ | `list_team_members` | List members of a specific team |
90
+ | `list_variable_groups` | List variable groups for a team or application |
91
+ | `get_variable_group` | Get details of a specific variable group |
92
+ | `create_variable_group` | Create a new variable group |
93
+ | `update_variable_group` | Update a variable group name or security setting |
94
+ | `delete_variable_group` | Delete a variable group |
95
+ | `list_variables` | List variables in a variable group |
96
+ | `get_variable` | Get a specific variable from a variable group |
97
+ | `update_variable` | Update a variable in a variable group |
98
+ | `delete_variable` | Delete a variable from a variable group |
99
+ | `bulk_import_variables` | Import multiple variables into a variable group |
100
+
77
101
  ### Build Failure Analysis
78
102
 
79
103
  When a build fails:
@@ -107,24 +131,9 @@ Versions are auto-incremented:
107
131
  - Build number = latest store build number + 1
108
132
  - Both platforms share the same version name (e.g., 1.0.0), synced from iOS
109
133
 
110
- ### Health Check Process
111
-
112
- After triggering a build:
113
- 1. Poll build status every 60 seconds until completion
114
- 2. Check both iOS and Android workflows independently
115
- 3. If one passes and one fails, report partial success and investigate the failure
116
- 4. Verify artifacts exist (IPA for iOS, AAB for Android)
117
- 5. Check store submission status after successful upload
118
-
119
- ### Log Analysis
134
+ ### Health Check and Log Analysis
120
135
 
121
- When analyzing Codemagic build logs:
122
- 1. Look for `ERROR`, `FAILURE`, `EXCEPTION`, `BUILD FAILED` patterns
123
- 2. Check Flutter analyze output for lint warnings/errors
124
- 3. Check test results for failures and skipped tests
125
- 4. Check code signing logs for certificate/profile issues
126
- 5. Check Fastlane output for store upload errors
127
- 6. Note which pipeline step failed and its exit code
136
+ After triggering a build, poll status every 60 seconds. Check both iOS and Android independently. If one passes and one fails, report partial success and investigate. Verify artifacts (IPA/AAB) and store submission status after success. In logs, look for `ERROR`, `FAILURE`, `EXCEPTION`, `BUILD FAILED`, check Flutter analyze, test results, code signing, and Fastlane output.
128
137
 
129
138
  ### Output Format
130
139
 
@@ -134,18 +143,7 @@ PLATFORM: iOS | Android | Both
134
143
  BUILD ID: [id]
135
144
  STATUS: queued | building | testing | publishing | finished | failed
136
145
  VERSION: [version]+[build_number]
137
-
138
- For failures:
139
- - Failed step: [step name]
140
- - Error: [summary]
141
- - Root cause: [analysis]
142
- - Fix: [action taken or recommended]
143
-
144
- For success:
145
- - iOS: [App Store submission status]
146
- - Android: [Google Play upload status]
147
- - Artifacts: [list]
148
-
146
+ RESULT: [success details or failure analysis with root cause and fix]
149
147
  RECOMMENDATION: [next action if needed]
150
148
  ```
151
149
 
@@ -375,7 +373,7 @@ Analyze Firestore usage patterns and optimize queries, indexes, and security rul
375
373
  | `scripts/check_changed.sh` | Detects changed files for conditional uploads |
376
374
  | `scripts/manage_version_ios.py` | iOS version auto-increment |
377
375
  | `scripts/check_google_play.py` | Google Play readiness checker |
378
- | `src/codemagic-api.mjs` | Codemagic REST API client |
376
+ | `.mcp.json (codemagic)` | Codemagic MCP server config and API token |
379
377
  | `fastlane/metadata/` | Store listing metadata (iOS + Android) |
380
378
  | `fastlane/iap_config.json` | In-app purchase configuration |
381
379
  | `web/deploy-cloudflare.mjs` | Cloudflare Pages deployment script |
package/src/install.mjs CHANGED
@@ -110,12 +110,12 @@ function setupGitHubActions(codemagicToken) {
110
110
  }
111
111
  }
112
112
 
113
- export async function runInstall(scope, isPostinstall = false) {
113
+ export async function runInstall(scope, isPostinstall = false, cliTokens = {}) {
114
114
  checkClaudeCli();
115
115
 
116
116
  console.log('Installing/updating Daemux Store Automator...');
117
117
 
118
- const tokens = await promptForTokens();
118
+ const tokens = await promptForTokens(cliTokens);
119
119
 
120
120
  const projectDir = process.cwd();
121
121
  const servers = getMcpServers(tokens);
package/src/mcp-setup.mjs CHANGED
@@ -32,6 +32,14 @@ export function getMcpServers(tokens) {
32
32
  };
33
33
  }
34
34
 
35
+ if (tokens.codemagicToken) {
36
+ servers.codemagic = {
37
+ command: 'npx',
38
+ args: ['-y', '@daemux/codemagic-mcp@latest'],
39
+ env: { CODEMAGIC_API_TOKEN: tokens.codemagicToken },
40
+ };
41
+ }
42
+
35
43
  return servers;
36
44
  }
37
45
 
@@ -75,7 +83,7 @@ export function removeMcpServers(projectDir) {
75
83
  const data = readJson(mcpPath);
76
84
  if (!data.mcpServers) return;
77
85
 
78
- const toRemove = ['playwright', 'mobile-mcp', 'stitch', 'cloudflare'];
86
+ const toRemove = ['playwright', 'mobile-mcp', 'stitch', 'cloudflare', 'codemagic'];
79
87
  for (const name of toRemove) {
80
88
  delete data.mcpServers[name];
81
89
  }
package/src/prompt.mjs CHANGED
@@ -12,11 +12,32 @@ function ask(rl, question) {
12
12
  });
13
13
  }
14
14
 
15
- export async function promptForTokens() {
15
+ function allTokensProvided(cliTokens) {
16
+ return (
17
+ cliTokens.stitchApiKey !== undefined &&
18
+ cliTokens.cloudflareToken !== undefined &&
19
+ cliTokens.cloudflareAccountId !== undefined &&
20
+ cliTokens.codemagicToken !== undefined
21
+ );
22
+ }
23
+
24
+ export async function promptForTokens(cliTokens = {}) {
25
+ const result = {
26
+ stitchApiKey: cliTokens.stitchApiKey ?? '',
27
+ cloudflareToken: cliTokens.cloudflareToken ?? '',
28
+ cloudflareAccountId: cliTokens.cloudflareAccountId ?? '',
29
+ codemagicToken: cliTokens.codemagicToken ?? '',
30
+ };
31
+
32
+ if (allTokensProvided(cliTokens)) {
33
+ console.log('All MCP tokens provided via CLI flags, skipping prompts.');
34
+ return result;
35
+ }
36
+
16
37
  if (!isInteractive()) {
17
38
  console.log('Non-interactive terminal detected, skipping token prompts.');
18
39
  console.log('Run "npx store-automator" manually to configure MCP tokens.');
19
- return { stitchApiKey: '', cloudflareToken: '', cloudflareAccountId: '', codemagicToken: '' };
40
+ return result;
20
41
  }
21
42
 
22
43
  const rl = createInterface({
@@ -30,30 +51,35 @@ export async function promptForTokens() {
30
51
  console.log('');
31
52
 
32
53
  try {
33
- const stitchApiKey = await ask(
34
- rl,
35
- 'Stitch MCP API Key (STITCH_API_KEY value): '
36
- );
37
-
38
- const cloudflareToken = await ask(
39
- rl,
40
- 'Cloudflare API Token: '
41
- );
42
-
43
- let cloudflareAccountId = '';
44
- if (cloudflareToken) {
45
- cloudflareAccountId = await ask(
54
+ if (cliTokens.stitchApiKey === undefined) {
55
+ result.stitchApiKey = await ask(
56
+ rl,
57
+ 'Stitch MCP API Key (STITCH_API_KEY value): '
58
+ );
59
+ }
60
+
61
+ if (cliTokens.cloudflareToken === undefined) {
62
+ result.cloudflareToken = await ask(
63
+ rl,
64
+ 'Cloudflare API Token: '
65
+ );
66
+ }
67
+
68
+ if (result.cloudflareToken && cliTokens.cloudflareAccountId === undefined) {
69
+ result.cloudflareAccountId = await ask(
46
70
  rl,
47
71
  'Cloudflare Account ID: '
48
72
  );
49
73
  }
50
74
 
51
- const codemagicToken = await ask(
52
- rl,
53
- 'Codemagic API Token (CM_API_TOKEN for CI/CD builds): '
54
- );
75
+ if (cliTokens.codemagicToken === undefined) {
76
+ result.codemagicToken = await ask(
77
+ rl,
78
+ 'Codemagic API Token (CM_API_TOKEN for CI/CD builds): '
79
+ );
80
+ }
55
81
 
56
- return { stitchApiKey, cloudflareToken, cloudflareAccountId, codemagicToken };
82
+ return result;
57
83
  } finally {
58
84
  rl.close();
59
85
  }
@@ -38,7 +38,7 @@ Prefer using the devops agent over direct Bash/SSH for structured operations.
38
38
  ## Configuration Files
39
39
 
40
40
  ### ci.config.yaml
41
- Single source of truth: credentials, app identity, store settings, web domain, Codemagic CI/CD (app_id for GitHub Actions auto-trigger, workflow IDs).
41
+ Single source of truth: credentials, app identity, store settings, web domain, Codemagic CI/CD (app_id for GitHub Actions auto-trigger, workflow IDs). The Codemagic API token is managed by the codemagic MCP server in `.mcp.json`.
42
42
 
43
43
  ### fastlane/metadata/ Structure
44
44
  All store listing texts are stored in fastlane directories and managed by the appstore-meta-creator agent:
@@ -57,6 +57,7 @@ web:
57
57
  # === CODEMAGIC CI/CD ===
58
58
  # Fill after creating app in Codemagic (https://codemagic.io/apps)
59
59
  # Find app_id in your Codemagic dashboard URL: codemagic.io/app/{app_id}
60
+ # API token is stored in .mcp.json (codemagic MCP server, set during install)
60
61
  codemagic:
61
62
  app_id: ""
62
63
  workflows: