mkit-cli 0.3.1__tar.gz

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.
Files changed (80) hide show
  1. mkit_cli-0.3.1/.gitattributes +19 -0
  2. mkit_cli-0.3.1/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
  3. mkit_cli-0.3.1/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. mkit_cli-0.3.1/.github/workflows/publish.yml +48 -0
  5. mkit_cli-0.3.1/.github/workflows/tests.yml +37 -0
  6. mkit_cli-0.3.1/.gitignore +7 -0
  7. mkit_cli-0.3.1/AGENTS.md +89 -0
  8. mkit_cli-0.3.1/CHANGELOG.md +57 -0
  9. mkit_cli-0.3.1/CONTRIBUTING.md +71 -0
  10. mkit_cli-0.3.1/LICENSE +21 -0
  11. mkit_cli-0.3.1/PKG-INFO +179 -0
  12. mkit_cli-0.3.1/README.md +147 -0
  13. mkit_cli-0.3.1/SECURITY.md +39 -0
  14. mkit_cli-0.3.1/docs/commands.md +1057 -0
  15. mkit_cli-0.3.1/docs/config.md +309 -0
  16. mkit_cli-0.3.1/docs/in-app-update.md +467 -0
  17. mkit_cli-0.3.1/docs/news-topics.md +65 -0
  18. mkit_cli-0.3.1/docs/store-art.md +245 -0
  19. mkit_cli-0.3.1/docs/store.md +139 -0
  20. mkit_cli-0.3.1/pyproject.toml +55 -0
  21. mkit_cli-0.3.1/scripts/gen_docs.py +14 -0
  22. mkit_cli-0.3.1/scripts/release.py +69 -0
  23. mkit_cli-0.3.1/src/mkit/__init__.py +5 -0
  24. mkit_cli-0.3.1/src/mkit/art.py +1220 -0
  25. mkit_cli-0.3.1/src/mkit/aso.py +359 -0
  26. mkit_cli-0.3.1/src/mkit/cli.py +176 -0
  27. mkit_cli-0.3.1/src/mkit/cloud/__init__.py +1 -0
  28. mkit_cli-0.3.1/src/mkit/cloud/auth.py +130 -0
  29. mkit_cli-0.3.1/src/mkit/cloud/fbproject.py +180 -0
  30. mkit_cli-0.3.1/src/mkit/cloud/firebase.py +164 -0
  31. mkit_cli-0.3.1/src/mkit/cloud/insight.py +286 -0
  32. mkit_cli-0.3.1/src/mkit/cloud/money.py +676 -0
  33. mkit_cli-0.3.1/src/mkit/cloud/play.py +497 -0
  34. mkit_cli-0.3.1/src/mkit/cloud/store.py +390 -0
  35. mkit_cli-0.3.1/src/mkit/commands/__init__.py +2 -0
  36. mkit_cli-0.3.1/src/mkit/commands/art.py +116 -0
  37. mkit_cli-0.3.1/src/mkit/commands/aso.py +130 -0
  38. mkit_cli-0.3.1/src/mkit/commands/dev.py +256 -0
  39. mkit_cli-0.3.1/src/mkit/commands/doctor.py +191 -0
  40. mkit_cli-0.3.1/src/mkit/commands/firebase_cmds.py +194 -0
  41. mkit_cli-0.3.1/src/mkit/commands/init.py +213 -0
  42. mkit_cli-0.3.1/src/mkit/commands/insight.py +110 -0
  43. mkit_cli-0.3.1/src/mkit/commands/meta.py +84 -0
  44. mkit_cli-0.3.1/src/mkit/commands/money.py +152 -0
  45. mkit_cli-0.3.1/src/mkit/commands/release.py +430 -0
  46. mkit_cli-0.3.1/src/mkit/commands/selfcmd.py +167 -0
  47. mkit_cli-0.3.1/src/mkit/commands/store.py +263 -0
  48. mkit_cli-0.3.1/src/mkit/config.py +146 -0
  49. mkit_cli-0.3.1/src/mkit/data/art/art.toml +119 -0
  50. mkit_cli-0.3.1/src/mkit/data/art/en.json +38 -0
  51. mkit_cli-0.3.1/src/mkit/data/datasafety-questions.csv +783 -0
  52. mkit_cli-0.3.1/src/mkit/datasafety.py +302 -0
  53. mkit_cli-0.3.1/src/mkit/device.py +246 -0
  54. mkit_cli-0.3.1/src/mkit/docgen.py +100 -0
  55. mkit_cli-0.3.1/src/mkit/errors.py +78 -0
  56. mkit_cli-0.3.1/src/mkit/git.py +95 -0
  57. mkit_cli-0.3.1/src/mkit/hooks.py +32 -0
  58. mkit_cli-0.3.1/src/mkit/kinds.py +350 -0
  59. mkit_cli-0.3.1/src/mkit/notify.py +49 -0
  60. mkit_cli-0.3.1/src/mkit/output.py +377 -0
  61. mkit_cli-0.3.1/src/mkit/proc.py +154 -0
  62. mkit_cli-0.3.1/src/mkit/registry.py +99 -0
  63. mkit_cli-0.3.1/src/mkit/safety.py +60 -0
  64. mkit_cli-0.3.1/src/mkit/secrets.py +148 -0
  65. mkit_cli-0.3.1/src/mkit/toolchain.py +210 -0
  66. mkit_cli-0.3.1/tests/conftest.py +26 -0
  67. mkit_cli-0.3.1/tests/fakeplay.py +290 -0
  68. mkit_cli-0.3.1/tests/test_art.py +435 -0
  69. mkit_cli-0.3.1/tests/test_aso.py +88 -0
  70. mkit_cli-0.3.1/tests/test_core.py +276 -0
  71. mkit_cli-0.3.1/tests/test_datasafety.py +253 -0
  72. mkit_cli-0.3.1/tests/test_device_logs.py +157 -0
  73. mkit_cli-0.3.1/tests/test_docs.py +28 -0
  74. mkit_cli-0.3.1/tests/test_firebase_apps.py +80 -0
  75. mkit_cli-0.3.1/tests/test_network_errors.py +82 -0
  76. mkit_cli-0.3.1/tests/test_products.py +359 -0
  77. mkit_cli-0.3.1/tests/test_release.py +413 -0
  78. mkit_cli-0.3.1/tests/test_store.py +247 -0
  79. mkit_cli-0.3.1/tests/test_studio.py +110 -0
  80. mkit_cli-0.3.1/uv.lock +701 -0
@@ -0,0 +1,19 @@
1
+ # Everything text lands in the working tree as LF, on every platform.
2
+ #
3
+ # Not a preference. mkit generates docs/commands.md from docstrings in the
4
+ # source, so a checkout that rewrote those files to CRLF made the generator
5
+ # produce a different reference than the one in the repo — the suite went red
6
+ # on Windows for a file nobody had touched. Pinning the endings removes the
7
+ # whole class of it.
8
+ * text=auto eol=lf
9
+
10
+ # Shell scripts must stay LF wherever they run.
11
+ *.sh text eol=lf
12
+
13
+ # Binary, never touched.
14
+ *.png binary
15
+ *.jpg binary
16
+ *.webp binary
17
+ *.ttf binary
18
+ *.otf binary
19
+ *.woff2 binary
@@ -0,0 +1,58 @@
1
+ name: Bug report
2
+ description: A command did the wrong thing, or stopped doing anything
3
+ labels: [bug]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Please do not paste a service account key or a `.env`.
9
+ `mkit <command> --json` is safe to share: it names missing credentials
10
+ and prints none of them.
11
+
12
+ - type: input
13
+ id: command
14
+ attributes:
15
+ label: The command
16
+ placeholder: mkit deploy --dry-run
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: output
22
+ attributes:
23
+ label: What it printed
24
+ description: The JSON envelope if you have it — `mkit <command> --json`.
25
+ render: shell
26
+ validations:
27
+ required: true
28
+
29
+ - type: textarea
30
+ id: expected
31
+ attributes:
32
+ label: What you expected instead
33
+ validations:
34
+ required: true
35
+
36
+ - type: dropdown
37
+ id: kind
38
+ attributes:
39
+ label: App kind
40
+ options: [flutter, android, android-wear, not sure]
41
+ validations:
42
+ required: true
43
+
44
+ - type: input
45
+ id: versions
46
+ attributes:
47
+ label: mkit and OS
48
+ description: "`mkit --version`, and which OS."
49
+ placeholder: "0.3.1 on Windows 11"
50
+ validations:
51
+ required: true
52
+
53
+ - type: textarea
54
+ id: doctor
55
+ attributes:
56
+ label: mkit doctor --json
57
+ description: Optional, and safe to paste — it never prints a secret.
58
+ render: json
@@ -0,0 +1,11 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Something only Play Console can do
4
+ url: https://github.com/almasumdev/mkit-cli/blob/main/docs/commands.md
5
+ about: >-
6
+ Creating an app, content rating, target audience, tester email lists,
7
+ production access and App access credentials have no API. `mkit manual`
8
+ lists them — those are not bugs in mkit.
9
+ - name: Security issue
10
+ url: https://github.com/almasumdev/mkit-cli/security/advisories/new
11
+ about: Anything exposing a credential or publishing without confirmation. Please report privately.
@@ -0,0 +1,48 @@
1
+ name: publish
2
+
3
+ # Publishes to PyPI when a version tag is pushed. No token lives here: PyPI's
4
+ # trusted publishing verifies the workflow's own identity, so there is nothing
5
+ # to leak and nothing to rotate.
6
+ #
7
+ # One-time setup, on https://pypi.org/manage/account/publishing/ :
8
+ # PyPI project name mkit-cli
9
+ # Owner almasumdev
10
+ # Repository mkit-cli
11
+ # Workflow publish.yml
12
+ # Environment pypi
13
+ # Then make a release: scripts/release.py minor go && git push --follow-tags
14
+
15
+ on:
16
+ push:
17
+ tags: ["v*"]
18
+ workflow_dispatch:
19
+
20
+ jobs:
21
+ build:
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: astral-sh/setup-uv@v5
26
+ with:
27
+ python-version: "3.12"
28
+ # The tag is not a release until the suite says so.
29
+ - run: uv sync --all-extras --dev
30
+ - run: uv run pytest -q
31
+ - run: uv build
32
+ - uses: actions/upload-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+
37
+ publish:
38
+ needs: build
39
+ runs-on: ubuntu-latest
40
+ environment: pypi
41
+ permissions:
42
+ id-token: write # what trusted publishing signs with
43
+ steps:
44
+ - uses: actions/download-artifact@v4
45
+ with:
46
+ name: dist
47
+ path: dist/
48
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,37 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ pytest:
11
+ # Three platforms because mkit shells out to git, gradle, adb and a JDK, and
12
+ # finds each of them differently per OS. Everything here runs against the
13
+ # fake Play service in tests/ — no job touches a real account.
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ os: [ubuntu-latest, macos-latest, windows-latest]
18
+ python: ["3.11", "3.13"]
19
+ runs-on: ${{ matrix.os }}
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v5
25
+ with:
26
+ python-version: ${{ matrix.python }}
27
+
28
+ - name: Install
29
+ run: uv sync --all-extras --dev
30
+
31
+ - name: Tests
32
+ run: uv run pytest -q
33
+
34
+ - name: Generated docs are current
35
+ # docs/commands.md is generated from the command registry; a stale one
36
+ # means a flag was changed without the reference following it.
37
+ run: uv run python scripts/gen_docs.py && git diff --exit-code docs/commands.md
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .pytest_cache/
5
+ dist/
6
+ *.egg-info/
7
+ .env
@@ -0,0 +1,89 @@
1
+ # mkit for AI agents
2
+
3
+ Read this before running mkit in any app.
4
+
5
+ ## The release rule
6
+
7
+ **Never run a release or publish command unless the user asked for that
8
+ exact action in this conversation.** Not to test, not to verify a change,
9
+ not as a "safe" dry run.
10
+
11
+ Release and publish commands:
12
+
13
+ | Command | Changes |
14
+ |---|---|
15
+ | `deploy` (including `deploy --dry-run`) | builds, bumps and commits the version, uploads to Play |
16
+ | `promote`, `rollout` | what users on a track get |
17
+ | `listing apply`, `datasafety apply`, `testers set` | the store listing and testing setup |
18
+ | `products apply` | in-app products and prices |
19
+ | `rules`, `config set`, `remoteconfig apply`, `remoteconfig rollback` | the live Firebase project |
20
+ | `reviews reply` | a public reply |
21
+ | `bump`, `share` | the app's version commit; a build handed to testers |
22
+
23
+ `deploy --dry-run` is on the list because it bumps and builds, uploads a
24
+ full bundle to Play and takes minutes; it is still release work.
25
+
26
+ When the user does ask:
27
+
28
+ 1. Say exactly what will happen (app, version, track, what changes).
29
+ 2. Run the plan form first where there is one (`listing plan`,
30
+ `products plan`, `remoteconfig plan`) and show the result.
31
+ 3. Run it with `--yes --confirm <package>`. The engine refuses without both
32
+ when it is not at a terminal (exit 6). `safety.no_prompt` does not change
33
+ this: it only spares a person at a terminal the typed confirmation. Approval covers that one action;
34
+ the next publish needs a new one.
35
+
36
+ ## Free to run
37
+
38
+ Everything else, when it helps the task: `doctor`, `status`, `version`,
39
+ `commands`, `schema`, `manual`, `self status`, `devices`, `listing plan`,
40
+ `products plan`, `remoteconfig plan`, `whatsnew check`, `datasafety check`,
41
+ `stats`, `vitals`, `crashes`, `reviews list`, `aso rank`, `aso score`,
42
+ `config show`, `testers show`, `products list`, `prices convert`,
43
+ `firebase sha`, `remoteconfig versions`.
44
+
45
+ `run` builds and installs on a device: only when the user wants the app on a
46
+ device, and only on the device they mean.
47
+
48
+ `studio` opens a window on the user's screen: only when they ask for it.
49
+
50
+ ## Discover, don't guess
51
+
52
+ - `mkit commands --json`: every command with its risk class, needed
53
+ features, and a JSON Schema of its input.
54
+ - `mkit schema <command> --json`: one command in detail.
55
+ - `mkit doctor --json`: which features this app uses and what is broken.
56
+ - `mkit manual`: what only Play Console can do. Tell the user; don't look for
57
+ a workaround.
58
+ - Reference: `docs/commands.md`, `docs/config.md`.
59
+
60
+ ## Output contract
61
+
62
+ Off a terminal mkit prints JSON on its own. stdout is exactly one envelope:
63
+
64
+ ```json
65
+ {"ok": true, "command": "...", "exit": 0, "result": {}, "warnings": [], "skipped": []}
66
+ {"ok": false, "command": "...", "exit": 3, "error": {"code": "...", "message": "...", "hint": "...", "retryable": false}}
67
+ ```
68
+
69
+ stderr has one JSON event per line (`step`, `done`, `detail`, `warn`,
70
+ `skipped`, `upload`, `log`). Branch on `exit`; follow `error.hint`.
71
+
72
+ | exit | meaning | what to do |
73
+ |---|---|---|
74
+ | 0 | ok | |
75
+ | 1 | failed | read `error`, report it |
76
+ | 2 | usage | fix the arguments |
77
+ | 3 | credential missing | tell the user which key `hint` names; never ask for the secret itself |
78
+ | 4 | not found | |
79
+ | 5 | conflict: remote changed, edit expired, already in review | re-run the plan, then ask again |
80
+ | 6 | needs confirmation | stop and ask the user |
81
+ | 7 | done, with skipped steps | report what `skipped` lists |
82
+ | 10 | plan found differences | show the diff |
83
+
84
+ ## Changing mkit itself
85
+
86
+ Changes go in the engine, never in an app's copy; follow
87
+ CONTRIBUTING.md (tests, regenerated docs, changelog, version).
88
+
89
+ Never read, print or copy `.env` files or credentials. Never commit them.
@@ -0,0 +1,57 @@
1
+ # Changelog
2
+
3
+ Every change is described here before it is released. Versions follow semantic
4
+ versioning (see CONTRIBUTING.md). An app states the oldest engine it works with
5
+ in `mkit.toml` (`requires = ">=0.3"`), and an older engine refuses to run for
6
+ it rather than doing the wrong thing.
7
+
8
+ ## Unreleased
9
+
10
+ ## 0.3.1 — first public release
11
+
12
+ mkit shipped a small studio's Android apps for a year before this; this is that
13
+ tool, with the studio's own house style and private services taken out. What is
14
+ here is the engine.
15
+
16
+ **Release.** `mkit deploy` in one command: preflight, a commit for whatever was
17
+ already uncommitted, the version bump in its own commit, Firestore rules, the
18
+ release build, the upload with mapping and release notes, the in-app update
19
+ document, a Telegram message, and a push. A failure before Play accepts the
20
+ build undoes the bump commit — and only if it is still at HEAD, so it can never
21
+ drop someone else's work. `promote`, `rollout` and `share` move a build on from
22
+ there.
23
+
24
+ **Store.** The listing, what's new, screenshots, the feature graphic, data
25
+ safety and in-app products all live in the repo, in every language, with `plan`
26
+ showing the difference against Play before `apply` sends it. `mkit art build`
27
+ draws the screenshots from real device captures.
28
+
29
+ **Insight.** `stats`, `vitals`, `crashes`, `reviews`, and `aso rank` /
30
+ `aso score` for where an app sits in Play search.
31
+
32
+ **Firebase.** Firestore rules, Remote Config (`plan`, `apply`, `pull`,
33
+ `rollback`), and an in-app update document the app reads at startup.
34
+
35
+ **Devices.** `run` builds and installs on a phone or emulator, `logs` follows
36
+ just that app, `studio` opens the project in Android Studio.
37
+
38
+ **Getting started.** `mkit init` writes `mkit.toml` and a commented `.env`
39
+ naming every credential, where it comes from and how to encode it; an existing
40
+ `.env` is never replaced, not even with `--force`. `mkit doctor` says what is
41
+ configured, what is broken, and which store commands an app cannot run because
42
+ it has no file for them. `mkit manual` lists the Play Console steps that have no
43
+ API — including production access for a new personal account and App access
44
+ credentials for an app behind a sign-in.
45
+
46
+ **Staying current.** `mkit self status` says whether a newer release is on PyPI,
47
+ and `mkit self update` names the upgrade command for whichever of uv, pipx or
48
+ pip installed it.
49
+
50
+ **For agents.** JSON output off a terminal, one envelope per run, an exit code
51
+ per outcome, a risk class per command, and a confirmation that publish-class
52
+ commands will not run without.
53
+
54
+ **Built and tested** on Linux, macOS and Windows against Python 3.11 and 3.13,
55
+ with a check that the generated command reference matches the code on every
56
+ platform. Releases publish to PyPI from a version tag through trusted
57
+ publishing, with no token stored anywhere.
@@ -0,0 +1,71 @@
1
+ # Contributing
2
+
3
+ Issues and pull requests are welcome. mkit drives real releases to the Play
4
+ Store, so the bar is less about style than about never surprising someone on
5
+ release day.
6
+
7
+ ## Getting set up
8
+
9
+ ```bash
10
+ git clone https://github.com/almasumdev/mkit-cli
11
+ cd mkit-cli
12
+ uv sync # or: pip install -e ".[dev]"
13
+ uv run pytest # the whole suite, against a fake Play service
14
+ ```
15
+
16
+ Nothing in the tests touches a real Google account. Play is faked by
17
+ `tests/fakeplay.py`, and it stays that way: a test that could publish is not a
18
+ test.
19
+
20
+ ## The checklist for a change
21
+
22
+ 1. Make the change. Keep anything app-specific out of the code.
23
+ 2. Add or update tests in `tests/`.
24
+ 3. `uv run python scripts/gen_docs.py` if a command, flag or summary changed —
25
+ `docs/commands.md` is generated from the command registry, and
26
+ `tests/test_docs.py` fails while it is stale.
27
+ 4. `uv run pytest` — everything passes.
28
+ 5. Describe the change under `## Unreleased` in `CHANGELOG.md`, in words
29
+ somebody using the command would understand.
30
+
31
+ ## Rules that must hold
32
+
33
+ - **A command that changes what users, testers or Play review see is
34
+ `risk='publish'`** and calls `safety.confirm` before changing anything.
35
+ `tests/test_docs.py` pins the list, so adding one is a deliberate act.
36
+ - **Nothing publishes in a test.** Use `tests/fakeplay.py` or `--dry-run`.
37
+ - **Secrets never reach output.** Read them through `secrets.Secrets`, which
38
+ registers each one for masking.
39
+ - **JSON output and exit codes are a contract.** Agents and scripts branch on
40
+ them; changing a shape or a code is a major version.
41
+ - **A per-app difference becomes an `mkit.toml` key**, documented in
42
+ `docs/config.md` — never a branch in the code on an app's name.
43
+
44
+ ## Versioning
45
+
46
+ Semantic versioning, in `src/mkit/__init__.py` only (`pyproject.toml` reads it
47
+ from there).
48
+
49
+ | Bump | When |
50
+ |---|---|
51
+ | patch | fixes; commands, flags, `mkit.toml` keys and JSON output unchanged |
52
+ | minor | new commands, flags, config keys or output fields; nothing existing breaks |
53
+ | major | anything an existing `mkit.toml`, script or agent would break on |
54
+
55
+ Releasing:
56
+
57
+ ```bash
58
+ uv run python scripts/release.py minor # shows the version and changelog entry
59
+ uv run python scripts/release.py minor go # tests, bumps, dates the changelog, tags
60
+ git push --follow-tags
61
+ ```
62
+
63
+ The script refuses with uncommitted changes, failing tests, or an empty
64
+ `## Unreleased` section, so every tag is a tested, described state.
65
+
66
+ ## Reporting a bug
67
+
68
+ Say which app kind (Flutter, native, Wear), the command you ran, and the JSON
69
+ output — `mkit <command> --json`. Never paste a service account key, and note
70
+ that `mkit doctor --json` is safe to share: it names which credentials are
71
+ missing without printing any of them.
mkit_cli-0.3.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nurullah Al-Masum
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.5
2
+ Name: mkit-cli
3
+ Version: 0.3.1
4
+ Summary: Release Android apps to Google Play from the command line: build, upload, listing, screenshots, data safety, in-app products, vitals and Firebase, in one tool built for humans and AI agents.
5
+ Project-URL: Homepage, https://github.com/almasumdev/mkit-cli
6
+ Project-URL: Documentation, https://github.com/almasumdev/mkit-cli/blob/main/docs/commands.md
7
+ Project-URL: Repository, https://github.com/almasumdev/mkit-cli
8
+ Project-URL: Issues, https://github.com/almasumdev/mkit-cli/issues
9
+ Project-URL: Changelog, https://github.com/almasumdev/mkit-cli/blob/main/CHANGELOG.md
10
+ Author: Nurullah Al-Masum
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: android,aso,firebase,flutter,google-play,release
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development :: Build Tools
24
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
25
+ Classifier: Topic :: System :: Software Distribution
26
+ Requires-Python: >=3.11
27
+ Requires-Dist: google-api-python-client>=2.150
28
+ Requires-Dist: google-auth>=2.35
29
+ Requires-Dist: pillow>=11
30
+ Requires-Dist: requests>=2.32
31
+ Description-Content-Type: text/markdown
32
+
33
+ # mkit
34
+
35
+ [![tests](https://github.com/almasumdev/mkit-cli/actions/workflows/tests.yml/badge.svg)](https://github.com/almasumdev/mkit-cli/actions/workflows/tests.yml)
36
+ [![licence: MIT](https://img.shields.io/badge/licence-MIT-blue.svg)](https://github.com/almasumdev/mkit-cli/blob/main/LICENSE)
37
+
38
+ One command-line tool for everything around an Android app that is not writing
39
+ it: build and install on a device, release to Google Play, keep the store
40
+ listing, screenshots, data safety and in-app products in your repo, read
41
+ installs, vitals, crashes and reviews, check search rank, and drive the
42
+ Firebase side (Firestore rules, Remote Config, an in-app update document).
43
+
44
+ Flutter and native Kotlin apps, including apps with a Wear OS module.
45
+
46
+ ```bash
47
+ mkit deploy # bump, build, upload to Play, publish, notify, push
48
+ mkit run -p # build and install on the phone
49
+ mkit status # what every track holds right now
50
+ mkit crashes # what is breaking in production
51
+ ```
52
+
53
+ A release is one command. `mkit deploy` bumps the version, commits it, builds
54
+ the bundle, uploads it with its mapping file and release notes, stages it on a
55
+ track, writes the update document, sends a message, and pushes — and if
56
+ anything fails before Play accepts the build, the version bump undoes itself so
57
+ the repo never claims a release that did not happen.
58
+
59
+ ## Why it exists
60
+
61
+ Shipping an Android app means a dozen small jobs that live in different places:
62
+ a Gradle command, the Play Console, the Firebase console, a screenshot folder
63
+ somebody renamed, a changelog nobody updated. Each is easy; together they are a
64
+ release day. mkit puts them behind one tool, with the app's settings in one
65
+ file, so the same release happens the same way every time — and so an AI agent
66
+ can run the safe parts without being handed your Play Console password.
67
+
68
+ It was built to ship a small studio's apps and has been doing that for a while.
69
+ It is opinionated where opinions save time and configurable where apps really
70
+ differ.
71
+
72
+ ## Install
73
+
74
+ Requires Python 3.11 or newer. [uv](https://docs.astral.sh/uv/) is the easiest
75
+ way in, and installs mkit as a command of its own rather than into a project:
76
+
77
+ ```bash
78
+ uv tool install mkit-cli
79
+ mkit --version
80
+ ```
81
+
82
+ With pipx: `pipx install mkit-cli`. With pip: `pip install mkit-cli`.
83
+
84
+ The latest from `main`, between releases:
85
+ `uv tool install git+https://github.com/almasumdev/mkit-cli`
86
+
87
+ `mkit self status` says whether a newer release is out, and `mkit self update`
88
+ gives the upgrade command for whichever of these installed it.
89
+
90
+ ## Getting started
91
+
92
+ In an app's folder:
93
+
94
+ ```bash
95
+ mkit init # writes mkit.toml, asking what it cannot work out
96
+ mkit doctor # what is configured, what is missing, and what to add
97
+ ```
98
+
99
+ `mkit.toml` is the whole of an app's configuration:
100
+
101
+ ```toml
102
+ [app]
103
+ name = "My App"
104
+ kind = "flutter" # flutter | android | android-wear
105
+ package = "com.example.app"
106
+
107
+ [play] # switches Play features on
108
+
109
+ [store] # store listing, art and data safety in the repo
110
+ listing_dir = "store/listing"
111
+ ```
112
+
113
+ Credentials never live in that file. A Google Play service account goes in
114
+ `.env` (per app) or `~/.mkit/.env` (shared); `mkit doctor` names the exact key
115
+ when one is missing, and never prints a secret. Every setting is documented in
116
+ [docs/config.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/config.md).
117
+
118
+ ## What it does
119
+
120
+ | | |
121
+ |---|---|
122
+ | **Develop** | `run`, `devices`, `logs`, `emu`, `studio`, `gradle`, `version`, `bump` |
123
+ | **Release** | `deploy`, `status`, `promote`, `rollout`, `share` |
124
+ | **Store** | `listing`, `whatsnew`, `datasafety`, `testers`, `art` |
125
+ | **Money** | `products`, `prices` |
126
+ | **Insight** | `stats`, `vitals`, `crashes`, `reviews`, `aso` |
127
+ | **Firebase** | `rules`, `config`, `remoteconfig`, `firebase` |
128
+
129
+ Every command, flag and example: [docs/commands.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/commands.md),
130
+ generated from the code so it cannot describe a flag that does not exist.
131
+
132
+ Commands are classed by what they can change — `read`, `plan`, `write`,
133
+ `publish` — and anything in the `publish` class refuses to run without an
134
+ explicit confirmation naming the package.
135
+
136
+ Some things have no API and must be done in the Play Console. `mkit manual`
137
+ lists them, so you know what is left rather than discovering it at release
138
+ time.
139
+
140
+ ## Working with AI agents
141
+
142
+ mkit answers in JSON whenever it is not attached to a terminal, with one
143
+ envelope on stdout and a documented exit code per outcome, so an agent can
144
+ branch on a result instead of reading prose. [AGENTS.md](https://github.com/almasumdev/mkit-cli/blob/main/AGENTS.md) is the
145
+ contract: which commands are safe to run unasked, which need a human to say so,
146
+ and what an agent must never do.
147
+
148
+ ## Documentation
149
+
150
+ | | |
151
+ |---|---|
152
+ | [docs/commands.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/commands.md) | every command and flag |
153
+ | [docs/config.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/config.md) | `mkit.toml`, the store and keyword files, credentials |
154
+ | [docs/store.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/store.md) | the `store/` folder: what lives where, in every language |
155
+ | [docs/store-art.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/store-art.md) | screenshots and the feature graphic, built from real captures |
156
+ | [docs/in-app-update.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/in-app-update.md) | how an app should check for updates: Play first, your policy second |
157
+ | [docs/news-topics.md](https://github.com/almasumdev/mkit-cli/blob/main/docs/news-topics.md) | news and offer notifications over FCM topics |
158
+ | [AGENTS.md](https://github.com/almasumdev/mkit-cli/blob/main/AGENTS.md) | the agent contract |
159
+ | [CONTRIBUTING.md](https://github.com/almasumdev/mkit-cli/blob/main/CONTRIBUTING.md) | changing mkit, tests, versioning |
160
+ | [SECURITY.md](https://github.com/almasumdev/mkit-cli/blob/main/SECURITY.md) | what counts as a security bug here, and how to report it |
161
+
162
+ ## Status and scope
163
+
164
+ Developed on Windows against real apps on Google Play; the code paths for
165
+ macOS and Linux exist but are less travelled, and there is no CI yet. The test
166
+ suite runs against a fake Play service — nothing in the tests touches a real
167
+ account.
168
+
169
+ It does not: create an app in the Play Console, answer content rating or target
170
+ audience questionnaires, manage tester email lists (the API only takes Google
171
+ Groups), or publish for you when managed publishing is on. `mkit manual` is the
172
+ full list.
173
+
174
+ Issues and pull requests are welcome. If you use it for your own apps, I would
175
+ like to hear what broke.
176
+
177
+ ## Licence
178
+
179
+ MIT. See [LICENSE](https://github.com/almasumdev/mkit-cli/blob/main/LICENSE).