asher-cli 0.0.1__tar.gz → 0.0.3__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.
- asher_cli-0.0.3/.env.example +3 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.githooks/pre-push +0 -3
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.github/workflows/ci.yml +1 -0
- asher_cli-0.0.3/.github/workflows/claude-code-review.yml +44 -0
- asher_cli-0.0.3/.github/workflows/claude.yml +50 -0
- asher_cli-0.0.3/.github/workflows/coverage.yml +24 -0
- asher_cli-0.0.3/.github/workflows/dependency-audit.yml +37 -0
- asher_cli-0.0.3/.github/workflows/release.yml +60 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/CLAUDE.md +44 -7
- {asher_cli-0.0.1 → asher_cli-0.0.3}/PKG-INFO +110 -15
- asher_cli-0.0.3/README.md +208 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/ROADMAP.md +2 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/app.py +7 -4
- asher_cli-0.0.3/asher/cats.py +93 -0
- asher_cli-0.0.3/asher/commands/__init__.py +442 -0
- asher_cli-0.0.3/asher/commands/base.py +81 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/connection/__init__.py +39 -5
- asher_cli-0.0.3/asher/login_flow.py +58 -0
- asher_cli-0.0.3/asher/slash-commands/__init__.py +19 -0
- asher_cli-0.0.3/asher/ui/__init__.py +253 -0
- asher_cli-0.0.3/asher/ui/style.tcss +134 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/pyproject.toml +18 -3
- asher_cli-0.0.3/tests/test_app_pilot.py +211 -0
- asher_cli-0.0.3/tests/test_auth.py +61 -0
- asher_cli-0.0.3/tests/test_auth_pilot.py +95 -0
- asher_cli-0.0.3/tests/test_cats.py +64 -0
- asher_cli-0.0.3/tests/test_commands_pilot.py +290 -0
- asher_cli-0.0.3/tests/test_connection.py +95 -0
- asher_cli-0.0.3/tests/test_connection_mixin.py +19 -0
- asher_cli-0.0.3/tests/test_monitoring.py +125 -0
- asher_cli-0.0.3/tests/test_ui.py +146 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/tests/testhelpers.py +29 -1
- {asher_cli-0.0.1 → asher_cli-0.0.3}/uv.lock +472 -1
- asher_cli-0.0.1/.github/workflows/release.yml +0 -36
- asher_cli-0.0.1/README.md +0 -113
- asher_cli-0.0.1/asher/cats.py +0 -40
- asher_cli-0.0.1/asher/commands/__init__.py +0 -350
- asher_cli-0.0.1/asher/slash-commands/__init__.py +0 -26
- asher_cli-0.0.1/asher/ui/__init__.py +0 -279
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.claude/skills/textual/SKILL.md +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.gitignore +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.vscode/launch.json +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.vscode/settings.json +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/.vscode/tasks.json +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/LICENSE +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/app.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/__init__.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/__main__.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/auth.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/helpers.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/asher/monitoring/__init__.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/requirements.txt +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/test.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/tests/__init__.py +0 -0
- {asher_cli-0.0.1 → asher_cli-0.0.3}/tests/conftest.py +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, ready_for_review, reopened]
|
|
6
|
+
# Optional: Only run on specific file changes
|
|
7
|
+
# paths:
|
|
8
|
+
# - "src/**/*.ts"
|
|
9
|
+
# - "src/**/*.tsx"
|
|
10
|
+
# - "src/**/*.js"
|
|
11
|
+
# - "src/**/*.jsx"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude-review:
|
|
15
|
+
# Optional: Filter by PR author
|
|
16
|
+
if: |
|
|
17
|
+
github.event.pull_request.user.login == 'external-contributor' ||
|
|
18
|
+
github.event.pull_request.user.login == 'new-developer' ||
|
|
19
|
+
github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
|
20
|
+
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
pull-requests: read
|
|
25
|
+
issues: read
|
|
26
|
+
id-token: write
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout repository
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 1
|
|
33
|
+
|
|
34
|
+
- name: Run Claude Code Review
|
|
35
|
+
id: claude-review
|
|
36
|
+
uses: anthropics/claude-code-action@v1
|
|
37
|
+
with:
|
|
38
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
39
|
+
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
|
40
|
+
plugins: 'code-review@claude-code-plugins'
|
|
41
|
+
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
|
42
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
43
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
44
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
pull-requests: read
|
|
24
|
+
issues: read
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read # Required for Claude to read CI results on PRs
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout repository
|
|
29
|
+
uses: actions/checkout@v4
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 1
|
|
32
|
+
|
|
33
|
+
- name: Run Claude Code
|
|
34
|
+
id: claude
|
|
35
|
+
uses: anthropics/claude-code-action@v1
|
|
36
|
+
with:
|
|
37
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
38
|
+
|
|
39
|
+
# This is an optional setting that allows Claude to read CI results on PRs
|
|
40
|
+
additional_permissions: |
|
|
41
|
+
actions: read
|
|
42
|
+
|
|
43
|
+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
|
44
|
+
# prompt: 'Update the pull request description to include a summary of changes.'
|
|
45
|
+
|
|
46
|
+
# Optional: Add claude_args to customize behavior and configuration
|
|
47
|
+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
|
48
|
+
# or https://code.claude.com/docs/en/cli-reference for available options
|
|
49
|
+
# claude_args: '--allowed-tools Bash(gh pr *)'
|
|
50
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Coverage
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 6 * * *" # daily at 06:00 UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
coverage:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v3
|
|
17
|
+
- run: uv sync --dev
|
|
18
|
+
- name: Run tests with coverage
|
|
19
|
+
run: uv run pytest tests/ --cov=asher --cov-report=lcov --cov-report=term-missing
|
|
20
|
+
- name: Upload to Coveralls
|
|
21
|
+
uses: coverallsapp/github-action@v2
|
|
22
|
+
with:
|
|
23
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
24
|
+
path-to-lcov: coverage.lcov
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Dependency Audit
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 0 * * 1" # every Monday at midnight UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
dependency-audit:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v3
|
|
18
|
+
- run: uv export --format requirements-txt > /tmp/requirements.txt
|
|
19
|
+
- name: Audit Python dependencies
|
|
20
|
+
uses: pypa/gh-action-pip-audit@v1.0.8
|
|
21
|
+
with:
|
|
22
|
+
inputs: /tmp/requirements.txt
|
|
23
|
+
- name: Upgrade lock file
|
|
24
|
+
run: uv lock --upgrade
|
|
25
|
+
- name: Open upgrade PR
|
|
26
|
+
uses: peter-evans/create-pull-request@v7
|
|
27
|
+
with:
|
|
28
|
+
commit-message: "chore: weekly dependency upgrades"
|
|
29
|
+
title: "chore: weekly dependency upgrades"
|
|
30
|
+
body: |
|
|
31
|
+
Automated weekly dependency upgrade via `uv lock --upgrade`.
|
|
32
|
+
|
|
33
|
+
Upgrades packages to their latest versions within the constraints
|
|
34
|
+
defined in `pyproject.toml`. Review the lock file diff before merging.
|
|
35
|
+
branch: chore/weekly-dep-upgrades
|
|
36
|
+
delete-branch: true
|
|
37
|
+
add-paths: uv.lock
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "release/*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write # needed to create GitHub Releases
|
|
10
|
+
id-token: write # needed for PyPI OIDC trusted publishing
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
name: Build distribution
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
outputs:
|
|
17
|
+
version: ${{ steps.version.outputs.version }}
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- name: Extract version from branch name
|
|
21
|
+
id: version
|
|
22
|
+
run: echo "version=${GITHUB_REF_NAME#release/}" >> "$GITHUB_OUTPUT"
|
|
23
|
+
- uses: astral-sh/setup-uv@v3
|
|
24
|
+
- run: uv build
|
|
25
|
+
- uses: actions/upload-artifact@v4
|
|
26
|
+
with:
|
|
27
|
+
name: dist
|
|
28
|
+
path: dist/
|
|
29
|
+
|
|
30
|
+
publish:
|
|
31
|
+
name: Publish to PyPI
|
|
32
|
+
needs: build
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
environment: pypi
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/download-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: dist
|
|
39
|
+
path: dist/
|
|
40
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
41
|
+
|
|
42
|
+
github-release:
|
|
43
|
+
name: Create GitHub Release
|
|
44
|
+
needs: [build, publish]
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- uses: actions/download-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
- name: Create release
|
|
53
|
+
env:
|
|
54
|
+
GH_TOKEN: ${{ github.token }}
|
|
55
|
+
VERSION: ${{ needs.build.outputs.version }}
|
|
56
|
+
run: |
|
|
57
|
+
gh release create "v${VERSION}" dist/* \
|
|
58
|
+
--title "v${VERSION}" \
|
|
59
|
+
--generate-notes \
|
|
60
|
+
--verify-tag=false
|
|
@@ -10,12 +10,22 @@ Terminal dashboard for Litter Robot (LR3/LR4/LR5) via the Whisker cloud API.
|
|
|
10
10
|
- **python-dotenv** — credential loading (`.env` fallback)
|
|
11
11
|
- **keyring>=24** — OS credential store (Windows Credential Manager / macOS Keychain / Linux Secret Service)
|
|
12
12
|
|
|
13
|
+
## Tooling
|
|
14
|
+
|
|
15
|
+
- **uv** — dependency management and task runner (`uv sync`, `uv run`)
|
|
16
|
+
- **poethepoet** — task aliases via `uv run poe <task>`
|
|
17
|
+
- **ruff** — linter and formatter
|
|
18
|
+
- **mypy** — static type checking
|
|
19
|
+
- **pytest + pytest-asyncio + pytest-cov** — tests
|
|
20
|
+
- **textual-dev** — CSS hot reload devtools
|
|
21
|
+
- **watchfiles** — Python auto-restart on file change
|
|
22
|
+
|
|
13
23
|
## Entry points
|
|
14
24
|
|
|
15
25
|
```
|
|
16
26
|
python app.py # compatibility shim (calls asher/__main__.py)
|
|
17
27
|
python -m asher # run as module
|
|
18
|
-
asher # after: pip install -e .
|
|
28
|
+
asher # after: uv sync && uv run asher OR pip install -e .
|
|
19
29
|
```
|
|
20
30
|
|
|
21
31
|
## Package structure
|
|
@@ -35,8 +45,16 @@ asher/
|
|
|
35
45
|
slash-commands/ Convention doc + future slash-command registry
|
|
36
46
|
|
|
37
47
|
tests/
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
testhelpers.py unit tests for helpers.py
|
|
49
|
+
test_cats.py CATS dict structure
|
|
50
|
+
test_auth.py LoginScreen CSS / structure
|
|
51
|
+
test_auth_pilot.py Textual Pilot integration tests for LoginScreen
|
|
52
|
+
test_app_pilot.py Textual Pilot integration tests for AsherApp
|
|
53
|
+
test_commands_pilot.py Textual Pilot integration tests for command dispatch
|
|
54
|
+
test_connection.py keyring helper functions
|
|
55
|
+
test_connection_mixin.py ConnectionMixin structure
|
|
56
|
+
test_monitoring.py MonitoringMixin async methods
|
|
57
|
+
test_ui.py UIMixin constants, CSS, helper existence
|
|
40
58
|
|
|
41
59
|
.github/workflows/
|
|
42
60
|
ci.yml ruff + mypy + pytest on every push/PR
|
|
@@ -52,8 +70,8 @@ Priority order on startup:
|
|
|
52
70
|
|
|
53
71
|
`.env` variable names (for fallback):
|
|
54
72
|
```
|
|
55
|
-
LITTER_ROBOT_USER=...
|
|
56
|
-
LITTER_ROBOT_PASSWORD=...
|
|
73
|
+
LITTER_ROBOT_USER=...
|
|
74
|
+
LITTER_ROBOT_PASSWORD=...
|
|
57
75
|
```
|
|
58
76
|
|
|
59
77
|
Keyring service name: `asher-cli`, keys `email` and `password`.
|
|
@@ -132,6 +150,25 @@ pylitterbot auto-detects robot type. Any attribute/method missing on a given mod
|
|
|
132
150
|
|
|
133
151
|
**Add a new cat state:** add entry to `CATS` dict in `asher/cats.py` (str for static, list[str] for animated), then call `_set_cat("name", "label")`.
|
|
134
152
|
|
|
135
|
-
**Run tests:** `pytest tests/` (or `uv run pytest` if using uv).
|
|
136
|
-
|
|
137
153
|
**File naming convention:** no underscores in filenames (except Python-required `__init__.py` and `__main__.py`).
|
|
154
|
+
|
|
155
|
+
## Dev workflow
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
uv sync # install all deps (including dev group)
|
|
159
|
+
uv run poe dev # run with CSS hot reload (textual --dev)
|
|
160
|
+
uv run poe watch # run with Python auto-restart on file change (watchfiles)
|
|
161
|
+
uv run poe test # run test suite
|
|
162
|
+
uv run poe check # ruff + mypy + pytest (same as CI)
|
|
163
|
+
uv run poe fix # auto-fix ruff issues
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Pre-push hook (`.githooks/pre-push`) runs: ruff check → ruff format --check → mypy. Tests are not in the hook — run them manually.
|
|
167
|
+
|
|
168
|
+
## Testing notes
|
|
169
|
+
|
|
170
|
+
- Pilot-based integration tests use `app.run_test()` with `await pilot.pause()` before querying widgets
|
|
171
|
+
- Helper app wrappers for screens must **not** start with `Test` (pytest will try to collect them); use e.g. `LoginTestApp`
|
|
172
|
+
- Mock external deps with `unittest.mock.AsyncMock` for async robot/account methods
|
|
173
|
+
- `from pylitterbot import Account` is a local import inside `_connect_worker` — patch it at `pylitterbot.Account`, not `asher.connection.Account`
|
|
174
|
+
- Coverage: ~76% overall; main gaps are async exception paths and `_connect_worker` auth flow
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: asher-cli
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Terminal dashboard for Litter Robot (LR3/LR4/LR5) via the Whisker cloud API
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -43,6 +43,14 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
|
|
44
44
|
# Asher CLI
|
|
45
45
|
|
|
46
|
+
[](https://pypi.org/project/asher-cli/)
|
|
47
|
+

|
|
48
|
+
[](https://pypi.org/project/asher-cli/)
|
|
49
|
+
[](LICENSE)
|
|
50
|
+
[](https://github.com/karanshukla/asher-cli/actions/workflows/ci.yml)
|
|
51
|
+
[](https://coveralls.io/github/karanshukla/asher-cli?branch=main)
|
|
52
|
+
[](https://github.com/astral-sh/ruff)
|
|
53
|
+
|
|
46
54
|
A Claude Code-style terminal dashboard for monitoring and controlling Litter Robot via the Whisker cloud API.
|
|
47
55
|
|
|
48
56
|
<img width="808" height="351" alt="image" src="https://github.com/user-attachments/assets/6599966f-837c-419c-8692-bfda3533e730" />
|
|
@@ -60,32 +68,36 @@ A Claude Code-style terminal dashboard for monitoring and controlling Litter Rob
|
|
|
60
68
|
|
|
61
69
|
## Install
|
|
62
70
|
|
|
71
|
+
### With pipx (recommended)
|
|
72
|
+
|
|
63
73
|
```bash
|
|
64
|
-
|
|
74
|
+
pipx install asher-cli
|
|
65
75
|
asher
|
|
66
76
|
```
|
|
67
77
|
|
|
68
|
-
|
|
78
|
+
`pipx` installs the CLI into an isolated environment and puts `asher` on your PATH automatically. Install `pipx` with `pip install pipx` if you don't have it.
|
|
79
|
+
|
|
80
|
+
### With pip
|
|
69
81
|
|
|
70
82
|
```bash
|
|
71
|
-
|
|
72
|
-
cd asher-cli
|
|
73
|
-
pip install -e .
|
|
83
|
+
pip install asher-cli
|
|
74
84
|
asher
|
|
75
85
|
```
|
|
76
86
|
|
|
77
|
-
###
|
|
87
|
+
### With uv
|
|
78
88
|
|
|
79
89
|
```bash
|
|
80
|
-
uv
|
|
81
|
-
|
|
90
|
+
uv tool install asher-cli
|
|
91
|
+
asher
|
|
82
92
|
```
|
|
83
93
|
|
|
94
|
+
### Run from source
|
|
95
|
+
|
|
84
96
|
```bash
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
uv
|
|
88
|
-
uv run
|
|
97
|
+
git clone https://github.com/karanshukla/asher-cli
|
|
98
|
+
cd asher-cli
|
|
99
|
+
uv sync
|
|
100
|
+
uv run asher
|
|
89
101
|
```
|
|
90
102
|
|
|
91
103
|
## Credentials
|
|
@@ -141,10 +153,93 @@ git checkout -b release/0.0.2
|
|
|
141
153
|
git push origin release/0.0.2
|
|
142
154
|
```
|
|
143
155
|
|
|
144
|
-
##
|
|
156
|
+
## Troubleshooting
|
|
157
|
+
|
|
158
|
+
**`asher` not found after `pip install asher-cli`**
|
|
159
|
+
|
|
160
|
+
Python's `Scripts` folder isn't on your PATH. Use `pipx` instead — it handles this automatically:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
pip install pipx
|
|
164
|
+
pipx install asher-cli
|
|
165
|
+
asher
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
If you're in a virtualenv, deactivate it first:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
deactivate
|
|
172
|
+
pip install pipx
|
|
173
|
+
pipx install asher-cli
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**`pipx: command not found`**
|
|
177
|
+
|
|
178
|
+
Run it as a module instead:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
python -m pip install pipx
|
|
182
|
+
python -m pipx install asher-cli
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Dev Setup
|
|
186
|
+
|
|
187
|
+
### 1. Clone and install
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
git clone https://github.com/karanshukla/asher-cli
|
|
191
|
+
cd asher-cli
|
|
192
|
+
uv sync # installs all deps including the dev group
|
|
193
|
+
git config core.hooksPath .githooks # lint + type checks run before every push
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 2. Configure environment (optional)
|
|
197
|
+
|
|
198
|
+
Copy `.env.example` to `.env` and fill in your credentials:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
cp .env.example .env
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```env
|
|
205
|
+
LITTER_ROBOT_USER=your@email.com
|
|
206
|
+
LITTER_ROBOT_PASSWORD=yourpassword
|
|
207
|
+
ASHER_CLI_DEV_MODE=true # sets version to "dev" instead of the installed package version
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 3. Run with hot reload
|
|
211
|
+
|
|
212
|
+
**CSS hot reload** — Textual's devtools watch inline `CSS` strings and `.tcss` files and reload them in-place without restarting:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
uv run poe dev
|
|
216
|
+
# equivalent to: textual run --dev asher/__main__.py
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Python auto-restart** — true in-process reload isn't possible with Textual's event loop, but `watchfiles` will kill and relaunch the app whenever a `.py` file changes in `asher/`:
|
|
145
220
|
|
|
146
221
|
```bash
|
|
147
|
-
uv run
|
|
222
|
+
uv run poe watch
|
|
223
|
+
# equivalent to: watchfiles --filter python 'python -m asher' asher
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
You can combine both — run `poe watch` for Python changes and it will naturally pick up CSS changes too on restart.
|
|
227
|
+
|
|
228
|
+
### 4. Run tests
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
uv run poe test # run all tests
|
|
232
|
+
uv run pytest tests/ --cov=asher # with coverage report
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### 5. Lint, format, type-check
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
uv run poe fix # auto-fix ruff issues
|
|
239
|
+
uv run poe lint # check only (no fixes)
|
|
240
|
+
uv run poe fmt # check formatting
|
|
241
|
+
uv run poe types # mypy
|
|
242
|
+
uv run poe check # run all of the above + tests (same as CI)
|
|
148
243
|
```
|
|
149
244
|
|
|
150
245
|
CI runs on Python 3.10 / 3.11 / 3.12 across Ubuntu, Windows, and macOS on every push.
|