@ait-co/console-cli 0.1.31 → 0.1.33

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.en.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm](https://img.shields.io/npm/v/@ait-co/console-cli)](https://www.npmjs.com/package/@ait-co/console-cli)
6
6
  [![license](https://img.shields.io/badge/license-BSD--3--Clause-blue)](https://github.com/apps-in-toss-community/console-cli/blob/main/LICENSE)
7
7
 
8
- > Pre-1.0 (`0.1.x`) — published to npm but the surface is still small. `whoami` / `login` / `logout` / `upgrade` are usable today; `deploy` / `logs` / `status` are next.
8
+ > Pre-1.0 (`0.1.x`) — published to npm. Auth, workspace, and mini-app commands (including bundle deploy and cert management) work end-to-end today; `app logs` is deferred until the backend endpoint is available. See [Status](#status) for the full command surface.
9
9
 
10
10
  `aitcc` is a community-maintained CLI for automating Apps in Toss developer console operations — log in once in a browser, then drive subsequent operations from your shell or from an AI coding agent via headless browser automation.
11
11
 
@@ -66,7 +66,7 @@ Add `--save keychain` to persist the credentials so the next `aitcc login` runs
66
66
 
67
67
  `aitcc upgrade` respects `GITHUB_TOKEN` to avoid anonymous GitHub API rate limits.
68
68
 
69
- Planned commands: `deploy`, `logs`, `status`.
69
+ Planned: `app logs` (pending backend endpoint availability).
70
70
 
71
71
  ### Project context (`aitcc.yaml`)
72
72
 
@@ -74,8 +74,8 @@ App- and workspace-scoped commands (`app status`, `app deploy`, `app certs ls`,
74
74
 
75
75
  ```yaml
76
76
  # aitcc.yaml
77
- workspaceId: 3095
78
- miniAppId: 31146
77
+ workspaceId: 12345
78
+ miniAppId: 67890
79
79
  ```
80
80
 
81
81
  Resolution priority (highest first):
@@ -86,7 +86,7 @@ Resolution priority (highest first):
86
86
  Each command prints a one-line context header to stderr so you always see what was resolved (suppressed under `--json` so machine-readable output is unaffected):
87
87
 
88
88
  ```
89
- [workspace: 3095 (from aitcc.yaml) · app: 31146 (from aitcc.yaml)]
89
+ [workspace: 12345 (from aitcc.yaml) · app: 67890 (from aitcc.yaml)]
90
90
  ```
91
91
 
92
92
  The walk stops at the nearest `.git` directory and never crosses `$HOME`. Passing `--workspace` overrides any yaml `miniAppId` (it may belong to a different workspace), but `AITCC_WORKSPACE` keeps it.
@@ -130,7 +130,7 @@ For one-shot CI runs (e.g. `aitcc app deploy` from a workflow), seed the runner
130
130
  # Desktop (already logged in):
131
131
  aitcc auth export --format env >> $GITHUB_ENV # or: aitcc auth export --format env → store as a secret
132
132
  # CI (with the secret exposed as $AITCC_SESSION):
133
- aitcc app deploy --bundle ./dist/app.zip --json
133
+ aitcc app deploy ./aitc-sdk-example.ait --json
134
134
  ```
135
135
 
136
136
  When `AITCC_SESSION` is set, every command reads the session from that env var instead of the local file. `logout` / `workspace use` / other write paths are silenced under env mode so a CI host never materialises a session file. Use `aitcc auth import --from-env` if you actually want the blob persisted to disk (mainly for restoring a desktop after a wipe).
@@ -168,7 +168,7 @@ Once per day per machine, a minimal anonymous ping is sent on every invocation.
168
168
 
169
169
  Three ways to opt out:
170
170
 
171
- - `AITC_TELEMETRY=off` environment variable — disables all telemetry for this shell session
171
+ - `AITCC_TELEMETRY=off` environment variable — disables all telemetry for this shell session
172
172
  - `--no-telemetry` flag — disables for this single invocation only (not permanent)
173
173
  - `aitcc telemetry tier0-off` — permanently opts out (persisted to the state file)
174
174
 
@@ -190,7 +190,14 @@ State file: `$XDG_CONFIG_HOME/aitcc/telemetry.json` (fallback `~/.config/aitcc/t
190
190
 
191
191
  ## Status
192
192
 
193
- `login`, `logout`, `whoami`, and `upgrade` are implemented end-to-end — `login` drives a real browser over CDP and `whoami` reads the live console member API. `deploy`, `logs`, `status` are next. See the [organization landing page](https://aitc.dev/) for the full roadmap.
193
+ The following command groups are implemented end-to-end:
194
+
195
+ - Auth & session: `login` / `logout` / `whoami` / `auth` (export/import)
196
+ - Workspace: `workspace` / `members` / `me` / `notices`
197
+ - Mini-app: `app` — `init` / `ls` / `show` / `status` / `deploy` / `register` / `ratings` / `reports` / `metrics` / `events` / `messages` / `share-rewards`, `app bundles` (`ls`/`deployed`/`upload`/`review`/`release`/`test-push`/`test-links`), `app certs` (`ls`/`show`/`issue`/`revoke`)
198
+ - Misc: Deploy Key issuance (`keys`), `telemetry`, `upgrade` (self-update), `completion` (shell completion)
199
+
200
+ `app logs` is deferred until the backend endpoint is available. See the [organization landing page](https://aitc.dev/) for the full roadmap.
194
201
 
195
202
  ## Pre-commit hook
196
203
 
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm](https://img.shields.io/npm/v/@ait-co/console-cli)](https://www.npmjs.com/package/@ait-co/console-cli)
6
6
  [![license](https://img.shields.io/badge/license-BSD--3--Clause-blue)](https://github.com/apps-in-toss-community/console-cli/blob/main/LICENSE)
7
7
 
8
- > 1.0 이전 단계 (`0.1.x`) — npm에 배포돼 있지만 표면은 아직 작습니다. 현재 `whoami` / `login` / `logout` / `upgrade`가 동작하고, `deploy` / `logs` / `status`는 다음 작업으로 진행됩니다.
8
+ > 1.0 이전 단계 (`0.1.x`) — npm에 배포돼 있습니다. 인증·워크스페이스·미니앱 명령(번들 배포, 인증서 관리 포함)이 end-to-end로 동작하며, `app logs`는 백엔드 endpoint 확보 구현 예정입니다. 전체 명령 표면은 [진행 상황](#진행-상황) 참조.
9
9
 
10
10
  `aitcc`는 앱인토스 개발자 콘솔을 자동화하는 커뮤니티 CLI입니다 — 브라우저로 한 번만 로그인하면 이후 작업은 셸이나 AI 코딩 에이전트가 headless 브라우저로 처리합니다.
11
11
 
@@ -66,7 +66,7 @@ AITCC_EMAIL=you@example.com AITCC_PASSWORD=… aitcc login --json
66
66
 
67
67
  `aitcc upgrade`는 GitHub API anonymous rate limit을 피하려고 `GITHUB_TOKEN`을 존중합니다.
68
68
 
69
- 예정 명령은 `deploy`, `logs`, `status` 입니다.
69
+ 예정 명령은 `app logs` 입니다 (백엔드 endpoint 확보 후).
70
70
 
71
71
  ### 프로젝트 컨텍스트 (`aitcc.yaml`)
72
72
 
@@ -74,8 +74,8 @@ app·workspace 범위 명령(`app status`, `app deploy`, `app certs ls`, `keys l
74
74
 
75
75
  ```yaml
76
76
  # aitcc.yaml
77
- workspaceId: 3095
78
- miniAppId: 31146
77
+ workspaceId: 12345
78
+ miniAppId: 67890
79
79
  ```
80
80
 
81
81
  해상도 우선순위 (높은 것부터):
@@ -86,7 +86,7 @@ miniAppId: 31146
86
86
  각 명령은 어떤 값이 resolve됐는지 stderr에 한 줄 헤더로 출력합니다 (`--json` 모드에선 machine-readable 출력에 영향 없도록 생략):
87
87
 
88
88
  ```
89
- [workspace: 3095 (from aitcc.yaml) · app: 31146 (from aitcc.yaml)]
89
+ [workspace: 12345 (from aitcc.yaml) · app: 67890 (from aitcc.yaml)]
90
90
  ```
91
91
 
92
92
  탐색은 가장 가까운 `.git` 디렉토리에서 멈추고 `$HOME` 위로는 절대 안 갑니다. `--workspace`로 workspace를 명시하면 yaml의 `miniAppId`는 무시되지만(다른 workspace 소속일 수 있음) `AITCC_WORKSPACE` env는 yaml miniApp을 유지합니다.
@@ -130,7 +130,7 @@ OS 키체인 대신 plain `0600` 파일을 쓰는 이유는 [CLAUDE.md](./CLAUDE
130
130
  # Desktop (이미 로그인된 상태):
131
131
  aitcc auth export --format env >> $GITHUB_ENV # 또는 secret으로 저장
132
132
  # CI ($AITCC_SESSION으로 secret 노출):
133
- aitcc app deploy --bundle ./dist/app.zip --json
133
+ aitcc app deploy ./aitc-sdk-example.ait --json
134
134
  ```
135
135
 
136
136
  `AITCC_SESSION`이 설정되면 모든 명령은 로컬 파일 대신 이 env var에서 세션을 읽습니다. env 모드에선 `logout` / `workspace use` 등의 write 경로가 비활성화돼 CI 호스트가 세션 파일을 절대 디스크에 떨어뜨리지 않습니다. blob을 disk에 영구 저장하고 싶다면 `aitcc auth import --from-env`를 쓰세요 (주로 desktop wipe 후 복구).
@@ -168,7 +168,7 @@ aitcc app deploy --bundle ./dist/app.zip --json
168
168
 
169
169
  opt-out 방법 (세 가지):
170
170
 
171
- - `AITC_TELEMETRY=off` 환경 변수 — 이 쉘 세션 전체 비활성
171
+ - `AITCC_TELEMETRY=off` 환경 변수 — 이 쉘 세션 전체 비활성
172
172
  - `--no-telemetry` 플래그 — 이 invocation만 비활성 (영구 X)
173
173
  - `aitcc telemetry tier0-off` — 영구 opt-out (state file에 저장)
174
174
 
@@ -190,7 +190,14 @@ aitcc telemetry tier0-on # Tier 0 다시 활성화
190
190
 
191
191
  ## 진행 상황
192
192
 
193
- `login`, `logout`, `whoami`, `upgrade`는 end-to-end 동작 — `login`은 CDP실제 브라우저를 띄우고 `whoami`는 live console member API를 호출합니다. `deploy`, `logs`, `status`가 다음 작업입니다. 전체 로드맵은 [organization landing page](https://aitc.dev/) 참조.
193
+ 다음 명령군이 end-to-end로 동작합니다:
194
+
195
+ - 인증·세션: `login` / `logout` / `whoami` / `auth` (export/import)
196
+ - 워크스페이스: `workspace` / `members` / `me` / `notices`
197
+ - 미니앱: `app` — `init` / `ls` / `show` / `status` / `deploy` / `register` / `ratings` / `reports` / `metrics` / `events` / `messages` / `share-rewards`, `app bundles` (`ls`/`deployed`/`upload`/`review`/`release`/`test-push`/`test-links`), `app certs` (`ls`/`show`/`issue`/`revoke`)
198
+ - 그 외: Deploy Key 발급(`keys`), `telemetry`, `upgrade`(self-update), `completion`(셸 자동완성)
199
+
200
+ `app logs`는 백엔드 endpoint 확보 후 구현 예정입니다. 전체 로드맵은 [organization landing page](https://aitc.dev/) 참조.
194
201
 
195
202
  ## Pre-commit hook
196
203
 
package/dist/cli.mjs CHANGED
@@ -1974,7 +1974,7 @@ async function runDeploy(args, deps = {}) {
1974
1974
  const release = Boolean(args.release);
1975
1975
  const confirm = Boolean(args.confirm);
1976
1976
  const releaseNotes = typeof args.releaseNotes === "string" ? args.releaseNotes : void 0;
1977
- if (requestReview && releaseNotes === void 0) {
1977
+ if (requestReview && (releaseNotes === void 0 || releaseNotes.trim() === "")) {
1978
1978
  if (args.json) emitJson({
1979
1979
  ok: false,
1980
1980
  reason: "missing-release-notes",
@@ -2280,7 +2280,7 @@ async function fetchTermsBlockers(workspaceId, session, apiOpts) {
2280
2280
  type,
2281
2281
  errorCode: WORKSPACE_TERM_ERROR_CODES[type],
2282
2282
  title: t.title,
2283
- action: `aitcc workspace terms --type ${type}`
2283
+ action: `aitcc workspace terms agree ${type}`
2284
2284
  });
2285
2285
  }
2286
2286
  return {
@@ -2510,6 +2510,7 @@ function validateManifest(raw, configDir) {
2510
2510
  if (!isTitleCaseWord(word)) throw new ManifestError("invalid-config", `titleEn word "${word}" must be title-case (first letter uppercase, rest lowercase); server-side rule, errorCode: miniApp.InvalidTitleEn`, "titleEn");
2511
2511
  }
2512
2512
  const appName = requireString(raw, "appName");
2513
+ if (!APP_NAME_REGEX.test(appName)) throw new ManifestError("invalid-config", `appName must be a kebab-case slug starting with a lowercase letter (got "${appName}"; server-side rule)`, "appName");
2513
2514
  const csEmail = requireString(raw, "csEmail");
2514
2515
  if (!isValidEmail$1(csEmail)) throw new ManifestError("invalid-config", `csEmail is not a valid email address (got ${csEmail})`, "csEmail");
2515
2516
  const subtitle = requireString(raw, "subtitle");
@@ -3097,7 +3098,7 @@ function emitImageDimensionError(json, err) {
3097
3098
  else process.stderr.write(`${err.message}\n`);
3098
3099
  }
3099
3100
  function emitTermsNotAccepted(json) {
3100
- const message = "The console requires several legal-agreement checkboxes before submitting a mini-app for review. Re-run with --accept-terms to attest that you have read and agree to each of them (see VALIDATION-RULES.md or the console UI), or use --dry-run to preview the payload without submitting.";
3101
+ const message = "The console requires several legal-agreement checkboxes before submitting a mini-app for review. Re-run with --accept-terms to attest that you have read and agree to each of them (see the console UI for the current list), or use --dry-run to preview the payload without submitting.";
3101
3102
  if (json) emitJson({
3102
3103
  ok: false,
3103
3104
  reason: "terms-not-accepted",
@@ -3139,7 +3140,9 @@ async function emitFailureAndExit(json, err) {
3139
3140
  return emitFailureFromError(json, err);
3140
3141
  }
3141
3142
  async function persistMiniAppIdToProject(json, miniAppId, cwd) {
3142
- if (typeof miniAppId !== "number" || !Number.isInteger(miniAppId) || miniAppId <= 0) return;
3143
+ const coerced = typeof miniAppId === "string" && /^\d+$/.test(miniAppId) ? Number(miniAppId) : miniAppId;
3144
+ if (typeof coerced !== "number" || !Number.isInteger(coerced) || coerced <= 0) return;
3145
+ const numericId = coerced;
3143
3146
  let ctx;
3144
3147
  try {
3145
3148
  ctx = await findProjectContext(cwd);
@@ -3151,12 +3154,12 @@ async function persistMiniAppIdToProject(json, miniAppId, cwd) {
3151
3154
  return;
3152
3155
  }
3153
3156
  if (ctx === null) {
3154
- if (!json) process.stderr.write(`tip: drop an aitcc.yaml with \`miniAppId: ${miniAppId}\` in your project root to skip --app on later commands.\n`);
3157
+ if (!json) process.stderr.write(`tip: drop an aitcc.yaml with \`miniAppId: ${numericId}\` in your project root to skip --app on later commands.\n`);
3155
3158
  return;
3156
3159
  }
3157
3160
  try {
3158
- const outcome = await writeProjectMiniAppId(ctx.source, miniAppId);
3159
- if (!json && outcome.status === "written") process.stderr.write(`Updated ${ctx.source} with miniAppId: ${miniAppId}.\n`);
3161
+ const outcome = await writeProjectMiniAppId(ctx.source, numericId);
3162
+ if (!json && outcome.status === "written") process.stderr.write(`Updated ${ctx.source} with miniAppId: ${numericId}.\n`);
3160
3163
  } catch (err) {
3161
3164
  if (!json) {
3162
3165
  const detail = err instanceof Error ? err.message : String(err);
@@ -5736,7 +5739,7 @@ const appCommand = defineCommand({
5736
5739
  },
5737
5740
  "accept-terms": {
5738
5741
  type: "boolean",
5739
- description: "Attest to the required console legal-agreement checkboxes (see VALIDATION-RULES.md). Required for real submits.",
5742
+ description: "Attest to the required console legal-agreement checkboxes. Required for real submits.",
5740
5743
  default: false
5741
5744
  },
5742
5745
  json: {
@@ -6218,7 +6221,7 @@ async function clearAuthState() {
6218
6221
  * 2. OS keychain entry whose email is recorded in `auth-state.json`.
6219
6222
  *
6220
6223
  * Returns `null` when no source is configured. The discriminated `kind`
6221
- * lets callers (e.g. PR β's login flow) tell why a credential was found
6224
+ * lets callers (e.g. the login flow) tell why a credential was found
6222
6225
  * without having to peek at process env themselves — useful for
6223
6226
  * "auto-login from CI" diagnostics.
6224
6227
  *
@@ -7051,7 +7054,7 @@ function parseAppsFlag(raw) {
7051
7054
  const lsCommand$3 = defineCommand({
7052
7055
  meta: {
7053
7056
  name: "ls",
7054
- description: "List console API keys in the selected workspace."
7057
+ description: "List Deploy Keys in the selected workspace."
7055
7058
  },
7056
7059
  args: {
7057
7060
  workspace: {
@@ -7086,11 +7089,11 @@ const lsCommand$3 = defineCommand({
7086
7089
  return exitAfterFlush(ExitCode.Ok);
7087
7090
  }
7088
7091
  if (keys.length === 0) {
7089
- process.stdout.write(`No API keys in workspace ${workspaceId}.\n`);
7090
- process.stderr.write("Hint: `aitcc keys create --name <label>` to issue one (deploy automation requires a key).\n");
7092
+ process.stdout.write(`No Deploy Keys in workspace ${workspaceId}.\n`);
7093
+ process.stderr.write("Hint: `aitcc keys create --name <label>` to issue one (deploy automation requires a Deploy Key).\n");
7091
7094
  return exitAfterFlush(ExitCode.Ok);
7092
7095
  }
7093
- process.stdout.write(`${keys.length} API key(s) in workspace ${workspaceId}:\n`);
7096
+ process.stdout.write(`${keys.length} Deploy Key(s) in workspace ${workspaceId}:\n`);
7094
7097
  const now = Date.now();
7095
7098
  for (const k of keys) {
7096
7099
  const name = k.name ?? "(unnamed)";
@@ -7106,7 +7109,7 @@ const lsCommand$3 = defineCommand({
7106
7109
  const createCommand = defineCommand({
7107
7110
  meta: {
7108
7111
  name: "create",
7109
- description: "Issue a new console API key. Plaintext is shown once."
7112
+ description: "Issue a new Deploy Key. Plaintext is shown once."
7110
7113
  },
7111
7114
  args: {
7112
7115
  name: {
@@ -7196,13 +7199,13 @@ const createCommand = defineCommand({
7196
7199
  const revokeCommand = defineCommand({
7197
7200
  meta: {
7198
7201
  name: "revoke",
7199
- description: "Disable a console API key by id."
7202
+ description: "Disable a Deploy Key by id."
7200
7203
  },
7201
7204
  args: {
7202
7205
  id: {
7203
7206
  type: "positional",
7204
7207
  required: true,
7205
- description: "API key id (from `aitcc keys ls`)."
7208
+ description: "Deploy Key id (from `aitcc keys ls`)."
7206
7209
  },
7207
7210
  workspace: {
7208
7211
  type: "string",
@@ -7230,7 +7233,7 @@ const revokeCommand = defineCommand({
7230
7233
  });
7231
7234
  return exitAfterFlush(ExitCode.Ok);
7232
7235
  }
7233
- process.stdout.write(`Revoked API key ${rawId} in workspace ${workspaceId}.\n`);
7236
+ process.stdout.write(`Revoked Deploy Key ${rawId} in workspace ${workspaceId}.\n`);
7234
7237
  return exitAfterFlush(ExitCode.Ok);
7235
7238
  } catch (err) {
7236
7239
  return emitFailureFromError(args.json, err);
@@ -7247,7 +7250,7 @@ function formatExpiry(expireTs, now) {
7247
7250
  const keysCommand = defineCommand({
7248
7251
  meta: {
7249
7252
  name: "keys",
7250
- description: "Manage console API keys used for deploy automation."
7253
+ description: "Manage Deploy Keys used for deploy automation."
7251
7254
  },
7252
7255
  subCommands: {
7253
7256
  ls: lsCommand$3,
@@ -9229,7 +9232,7 @@ function resolveVersion() {
9229
9232
  if (typeof injected === "string" && injected.length > 0) return injected;
9230
9233
  } catch {}
9231
9234
  try {
9232
- return "0.1.31";
9235
+ return "0.1.33";
9233
9236
  } catch {}
9234
9237
  return "0.0.0-dev";
9235
9238
  }
@@ -9501,7 +9504,7 @@ async function sendTier0Ping(endpoint, version) {
9501
9504
  * Usage: import { trackInvocation, trackTier0Ping } from './telemetry/index.js'
9502
9505
  *
9503
9506
  * Tier 0 (opt-out): anonymous daily ping. Fires on every invocation; client-side
9504
- * daily dedupe via tier0LastSent. Respects AITC_TELEMETRY=off, --no-telemetry,
9507
+ * daily dedupe via tier0LastSent. Respects AITCC_TELEMETRY=off, --no-telemetry,
9505
9508
  * and permanent tier0OptOut flag.
9506
9509
  *
9507
9510
  * Tier 1 (opt-in): detailed events. First invocation on a TTY prompts the user;
@@ -9555,7 +9558,7 @@ async function promptConsent() {
9555
9558
  */
9556
9559
  function isTelemetryGloballyDisabled(noTelemetryFlag) {
9557
9560
  if (noTelemetryFlag) return true;
9558
- const env = process.env.AITC_TELEMETRY;
9561
+ const env = process.env.AITCC_TELEMETRY;
9559
9562
  if (env !== void 0 && env.toLowerCase() === "off") return true;
9560
9563
  return false;
9561
9564
  }
@@ -9563,7 +9566,7 @@ function isTelemetryGloballyDisabled(noTelemetryFlag) {
9563
9566
  * Send a Tier 0 anonymous daily ping (fire-and-forget).
9564
9567
  *
9565
9568
  * Skips if:
9566
- * - AITC_TELEMETRY=off or --no-telemetry flag
9569
+ * - AITCC_TELEMETRY=off or --no-telemetry flag
9567
9570
  * - tier0OptOut === true in the state file
9568
9571
  * - already sent today (tier0LastSent === today's ISO date)
9569
9572
  *
@@ -11039,7 +11042,7 @@ const main = defineCommand({
11039
11042
  meta: {
11040
11043
  name: "aitcc",
11041
11044
  version: VERSION,
11042
- description: "aitcc — Apps in Toss Community Console CLI. Unofficial, not affiliated with Toss."
11045
+ description: "aitcc — Apps in Toss Community Console CLI. Community open-source project."
11043
11046
  },
11044
11047
  subCommands: {
11045
11048
  whoami: whoamiCommand,