lkr-dev-cli 0.0.55__tar.gz → 0.0.57__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 (116) hide show
  1. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.github/workflows/ci.yml +13 -2
  2. lkr_dev_cli-0.0.57/.gitignore +9 -0
  3. lkr_dev_cli-0.0.57/.pre-commit-config.yaml +28 -0
  4. lkr_dev_cli-0.0.57/AGENTS.md +7 -0
  5. lkr_dev_cli-0.0.57/Makefile +40 -0
  6. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/PKG-INFO +123 -37
  7. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/README.md +117 -36
  8. lkr_dev_cli-0.0.57/TODO.md +33 -0
  9. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/__init__.py +2 -0
  10. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/classes.py +30 -1
  11. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/main.py +132 -0
  12. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/main.py +3 -0
  13. lkr_dev_cli-0.0.57/lkr/parse/__init__.py +167 -0
  14. lkr_dev_cli-0.0.57/lkr/parse/constants.py +252 -0
  15. lkr_dev_cli-0.0.57/lkr/parse/dag.py +271 -0
  16. lkr_dev_cli-0.0.57/lkr/parse/lookml.py +704 -0
  17. lkr_dev_cli-0.0.57/lkr/parse/lookml_to_api.py +1643 -0
  18. lkr_dev_cli-0.0.57/lkr/parse/main.py +270 -0
  19. lkr_dev_cli-0.0.57/lkr/parse/sql.py +243 -0
  20. lkr_dev_cli-0.0.57/lkr/parse/sql_to_lookml.py +991 -0
  21. lkr_dev_cli-0.0.57/lkr/parse/types.py +324 -0
  22. lkr_dev_cli-0.0.57/lkr/schema/__init__.py +15 -0
  23. lkr_dev_cli-0.0.57/lkr/schema/_schema_rs.so +0 -0
  24. lkr_dev_cli-0.0.57/lkr/schema/builder.py +163 -0
  25. lkr_dev_cli-0.0.57/lkr/schema/dynamic_fields.py +113 -0
  26. lkr_dev_cli-0.0.57/lkr/schema/fields.py +119 -0
  27. lkr_dev_cli-0.0.57/lkr/schema/filter_expressions.py +242 -0
  28. lkr_dev_cli-0.0.57/lkr/schema/main.py +202 -0
  29. lkr_dev_cli-0.0.57/lkr/schema/rust/Cargo.lock +345 -0
  30. lkr_dev_cli-0.0.57/lkr/schema/rust/Cargo.toml +25 -0
  31. lkr_dev_cli-0.0.57/lkr/schema/rust/src/lib.rs +1063 -0
  32. lkr_dev_cli-0.0.57/lkr/schema/validator.py +64 -0
  33. lkr_dev_cli-0.0.57/lkr/tools/agents.py +987 -0
  34. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/tools/main.py +2 -0
  35. lkr_dev_cli-0.0.57/lkr.md +524 -0
  36. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/pyproject.toml +9 -2
  37. lkr_dev_cli-0.0.57/scripts/schema/README.md +60 -0
  38. lkr_dev_cli-0.0.57/scripts/schema/__init__.py +1 -0
  39. lkr_dev_cli-0.0.57/scripts/schema/history.py +317 -0
  40. lkr_dev_cli-0.0.57/tests/test_agents_tools.py +469 -0
  41. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_dependency_resolution.py +3 -1
  42. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_extended_sdk_methods.py +88 -0
  43. lkr_dev_cli-0.0.57/tests/test_parse_lookml.py +1707 -0
  44. lkr_dev_cli-0.0.57/tests/test_parse_sql.py +101 -0
  45. lkr_dev_cli-0.0.57/tests/test_schema.py +857 -0
  46. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/uv.lock +687 -381
  47. lkr_dev_cli-0.0.55/.gitignore +0 -5
  48. lkr_dev_cli-0.0.55/Makefile +0 -26
  49. lkr_dev_cli-0.0.55/lkr.md +0 -373
  50. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/SKILL.md +0 -0
  51. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/examples.py +0 -0
  52. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/order_items_query.py +0 -0
  53. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/personal_folder_dashboards.py +0 -0
  54. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/readme.py +0 -0
  55. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/traverse_folders.py +0 -0
  56. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/SKILL.md +0 -0
  57. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/bq_view_lookml_generator.py +0 -0
  58. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/configure_model.py +0 -0
  59. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/create_custom_view.py +0 -0
  60. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/deploy_and_reset_workspace.py +0 -0
  61. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/ensure_project_and_model.py +0 -0
  62. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/generate_lookml.py +0 -0
  63. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/init_project.py +0 -0
  64. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/inspect_connections.py +0 -0
  65. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/migrate_dashboard_to_udd.py +0 -0
  66. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/upload_assets.py +0 -0
  67. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/validate_and_commit.py +0 -0
  68. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.github/workflows/release.yml +0 -0
  69. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.github/workflows/website.yml +0 -0
  70. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.python-version +0 -0
  71. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.vscode/launch.json +0 -0
  72. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/.vscode/settings.json +0 -0
  73. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/Dockerfile +0 -0
  74. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/LICENSE +0 -0
  75. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/cloudbuild.yaml +0 -0
  76. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/codemode.md +0 -0
  77. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/__init__.py +0 -0
  78. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/auth/__init__.py +0 -0
  79. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/auth/main.py +0 -0
  80. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/auth/oauth.py +0 -0
  81. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/auth_service.py +0 -0
  82. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/classes.py +0 -0
  83. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/LOCAL.md +0 -0
  84. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/__init__.py +0 -0
  85. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/constant.py +0 -0
  86. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/download_swagger.py +0 -0
  87. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/examples.py +0 -0
  88. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/help.py +0 -0
  89. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/main.py +0 -0
  90. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/readme.py +0 -0
  91. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/swagger.json +0 -0
  92. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/codemode/type.py +0 -0
  93. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/constants.py +0 -0
  94. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/custom_types.py +0 -0
  95. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/exceptions.py +0 -0
  96. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/logger.py +0 -0
  97. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/mcp/classes.py +0 -0
  98. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/mcp/main.py +0 -0
  99. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/mcp/utils.py +0 -0
  100. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/observability/classes.py +0 -0
  101. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/observability/embed_container.html +0 -0
  102. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/observability/main.py +0 -0
  103. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/observability/utils.py +0 -0
  104. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/tools/classes.py +0 -0
  105. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/tools/lookml.py +0 -0
  106. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr/tools/permission_deprecation.py +0 -0
  107. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/lkr_dev_cli/__init__.py +0 -0
  108. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/TESTING.md +0 -0
  109. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_codemode.py +0 -0
  110. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_deps.sh +0 -0
  111. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_init_sdk.py +0 -0
  112. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_lookml_tools.py +0 -0
  113. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_oauth_account.py +0 -0
  114. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_permission_deprecation.py +0 -0
  115. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/tests/test_version.py +0 -0
  116. {lkr_dev_cli-0.0.55 → lkr_dev_cli-0.0.57}/ty.toml +0 -0
@@ -15,6 +15,11 @@ jobs:
15
15
  - name: Checkout code
16
16
  uses: actions/checkout@v4
17
17
 
18
+ - name: Setup Rust toolchain
19
+ uses: dtolnay/rust-toolchain@stable
20
+ with:
21
+ components: clippy, rustfmt, llvm-tools-preview
22
+
18
23
  - name: Setup Python
19
24
  uses: actions/setup-python@v4
20
25
  with:
@@ -29,9 +34,16 @@ jobs:
29
34
  run: |
30
35
  uv sync --extra all
31
36
 
32
- - name: Run with pytest
37
+ - name: Run Rust clippy, unit tests, and build extension
38
+ run: |
39
+ cargo clippy --manifest-path lkr/schema/rust/Cargo.toml -- -D warnings
40
+ cargo test --no-default-features --manifest-path lkr/schema/rust/Cargo.toml
41
+ make schema-rs
42
+
43
+ - name: Run pytest
33
44
  run: |
34
45
  uv run pytest tests/ -v
46
+ uv run pytest tests/test_schema.py -v --cov=lkr.schema --cov=scripts.schema --cov-report=term-missing
35
47
 
36
48
  - name: Run ruff
37
49
  run: |
@@ -40,4 +52,3 @@ jobs:
40
52
  - name: Run ty
41
53
  run: |
42
54
  uv run ty check
43
-
@@ -0,0 +1,9 @@
1
+ *.pyc
2
+ __pycache__
3
+ .venv
4
+ tmp
5
+ .env
6
+ lkr/schema/rust/target/
7
+ coverage.xml
8
+ .coverage
9
+ *.profraw
@@ -0,0 +1,28 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/uv-pre-commit
3
+ rev: 0.7.12
4
+ hooks:
5
+ - id: uv-lock
6
+ args: ["--default-index", "https://pypi.org/simple", "--no-config"]
7
+ - repo: local
8
+ hooks:
9
+ - id: docs
10
+ name: generate cli docs
11
+ entry: bash -c "make docs && git add lkr.md"
12
+ language: system
13
+ pass_filenames: false
14
+ - id: ruff-check
15
+ name: ruff check
16
+ entry: uv run ruff check .
17
+ language: system
18
+ pass_filenames: false
19
+ - id: ty-check
20
+ name: ty check
21
+ entry: uv run ty check
22
+ language: system
23
+ pass_filenames: false
24
+ - id: test-and-coverage
25
+ name: pytest & rust coverage
26
+ entry: make coverage
27
+ language: system
28
+ pass_filenames: false
@@ -0,0 +1,7 @@
1
+ # AGENTS.md
2
+
3
+ ## Pre-Commit & Testing Workflow
4
+
5
+ - **Do NOT run full test suites (`pytest` without target files, `make coverage`, `make test-rs`, `ruff check .`, `ty check`) manually.**
6
+ - If you need to verify a specific test while working, only run the single targeted test file (e.g. `uv run pytest tests/test_foo.py --no-cov`).
7
+ - Full linting, type-checking, Rust tests, and test coverage are configured in [`.pre-commit-config.yaml`](.pre-commit-config.yaml) and run automatically at commit time.
@@ -0,0 +1,40 @@
1
+ .PHONY: docs test-deps codemode-test codemode-start schema-rs test-rs coverage-py coverage-rs coverage
2
+
3
+ docs:
4
+ uv run typer lkr/main.py utils docs --output lkr.md
5
+
6
+ test-deps:
7
+ python tests/test_dependency_resolution.py
8
+
9
+ codemode-test:
10
+ uv run pytest tests/test_codemode.py
11
+
12
+ schema-rs:
13
+ cargo build --release --manifest-path lkr/schema/rust/Cargo.toml && cp lkr/schema/rust/target/release/lib_schema_rs.so lkr/schema/_schema_rs.so
14
+
15
+ test-rs:
16
+ cargo clippy --manifest-path lkr/schema/rust/Cargo.toml -- -D warnings
17
+ cargo test --no-default-features --manifest-path lkr/schema/rust/Cargo.toml
18
+
19
+ coverage-py:
20
+ uv run pytest tests/test_schema.py --cov=lkr.schema --cov=scripts.schema --cov-report=term-missing --cov-report=xml:coverage.xml
21
+
22
+ coverage-rs:
23
+ RUSTFLAGS="-C instrument-coverage" LLVM_PROFILE_FILE="target/cov-%p-%m.profraw" cargo test --no-default-features --manifest-path lkr/schema/rust/Cargo.toml
24
+
25
+ coverage: test-rs coverage-py coverage-rs
26
+
27
+ download-swagger:
28
+ uv run python lkr/codemode/download_swagger.py
29
+
30
+ codemode-start:
31
+ @echo "Add this to your mcpServers config:"
32
+ @echo "{"
33
+ @echo " \"mcpServers\": {"
34
+ @echo " \"lkr_codemode\": {"
35
+ @echo " \"command\": \"uvx\","
36
+ @echo " \"args\": [\"-q\", \"--from\", \"lkr-dev-cli[codemode]\", \"lkr\", \"code-mode\", \"run\"]"
37
+ @echo " }"
38
+ @echo " }"
39
+ @echo "}"
40
+ uv run -q lkr code-mode run
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lkr-dev-cli
3
- Version: 0.0.55
3
+ Version: 0.0.57
4
4
  Summary: lkr: a command line interface for looker
5
5
  Author: bwebs
6
6
  License-Expression: MIT
@@ -18,8 +18,10 @@ Provides-Extra: all
18
18
  Requires-Dist: duckdb>=1.3.1; extra == 'all'
19
19
  Requires-Dist: fastapi[standard]>=0.136.3; extra == 'all'
20
20
  Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'all'
21
+ Requires-Dist: nodejs-wheel>=24.19.0; extra == 'all'
21
22
  Requires-Dist: pydantic-monty==0.0.23; extra == 'all'
22
23
  Requires-Dist: selenium>=4.34.0; extra == 'all'
24
+ Requires-Dist: sqlglot>=30.19.0; extra == 'all'
23
25
  Provides-Extra: code-mode
24
26
  Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'code-mode'
25
27
  Requires-Dist: pydantic-monty==0.0.23; extra == 'code-mode'
@@ -33,6 +35,9 @@ Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'mcp'
33
35
  Provides-Extra: observability
34
36
  Requires-Dist: fastapi[standard]>=0.136.3; extra == 'observability'
35
37
  Requires-Dist: selenium>=4.34.0; extra == 'observability'
38
+ Provides-Extra: parse
39
+ Requires-Dist: nodejs-wheel>=24.19.0; extra == 'parse'
40
+ Requires-Dist: sqlglot>=30.19.0; extra == 'parse'
36
41
  Provides-Extra: tools
37
42
  Requires-Dist: fastapi[standard]>=0.136.3; extra == 'tools'
38
43
  Description-Content-Type: text/markdown
@@ -43,9 +48,9 @@ The `lkr` cli is a tool for interacting with Looker. It combines Looker's SDK an
43
48
 
44
49
  ## Usage
45
50
 
46
- `uv` makes everyone's life easier. Go [install it](https://docs.astral.sh/uv/getting-started/installation/). You can start using `lkr` by running `uvx lkr-dev-cli --help`.
51
+ `uv` makes everyone's life easier. Go [install it](https://docs.astral.sh/uv/getting-started/installation/). You can start using `lkr` without installing by running `uvx lkr-dev-cli --help`.
47
52
 
48
- Alternatively, you can install `lkr` with `pip install lkr-dev-cli[all]` and use commands directly like `lkr <command>`.
53
+ Alternatively, you can install `lkr` with `uv tool install "lkr-dev-cli[all]"` (or `pip install "lkr-dev-cli[all]"`) and run commands directly like `lkr <command>`.
49
54
 
50
55
  We also have a public docker image that you can use to run `lkr` commands.
51
56
 
@@ -53,6 +58,26 @@ We also have a public docker image that you can use to run `lkr` commands.
53
58
  docker run -it --rm us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest lkr --help
54
59
  ```
55
60
 
61
+ ## Installing and upgrading with `uv tool`
62
+
63
+ Install `lkr` globally on your PATH to run `lkr` (or `lkr-dev-cli`) directly without `uvx`:
64
+
65
+ ```bash
66
+ # Install with all optional extras (mcp, code-mode, observability, tools)
67
+ uv tool install "lkr-dev-cli[all]"
68
+
69
+ # Verify installation
70
+ lkr --help
71
+ ```
72
+
73
+ Upgrade an existing installation to the latest release:
74
+
75
+ ```bash
76
+ uv tool upgrade lkr-dev-cli
77
+
78
+ # Or force reinstall the latest version
79
+ uv tool install --upgrade --reinstall "lkr-dev-cli[all]"
80
+ ```
56
81
 
57
82
  ## Login
58
83
 
@@ -112,11 +137,11 @@ Go to the Looker API Explorer for Register OAuth App (https://your.looker.instan
112
137
  - This only needs to be done once per instance
113
138
 
114
139
 
115
- ## Code Mode
140
+ ## Code mode
116
141
 
117
- Execute Python code safely with full Looker SDK coverage within a secure sandbox environment (`Monty`). It dynamically inspects the Looker SDK for all public methods and injects them into the sandbox safely, supporting both Model Context Protocol (MCP) server mode and direct standalone CLI execution.
142
+ Execute Python code with Looker SDK coverage inside a `Monty` sandbox. It inspects the Looker SDK for public methods and injects them into the sandbox for both Model Context Protocol (MCP) server mode and standalone CLI execution.
118
143
 
119
- ### Direct CLI Execution (Sandbox Mode)
144
+ ### Direct CLI execution (sandbox mode)
120
145
  Run scripts or inline code directly against your active Looker instance:
121
146
  ```bash
122
147
  # Execute inline Python code
@@ -126,17 +151,17 @@ uvx lkr-dev-cli code-mode sandbox --code="return me()"
126
151
  uvx lkr-dev-cli code-mode sandbox --file=./path/to/script.py
127
152
  ```
128
153
 
129
- ### Agent Skill (`lkr-code-mode`)
154
+ ### Agent skill (`lkr-code-mode`)
130
155
 
131
- For AI coding agents (Gemini CLI, Claude Code, Cursor, Copilot), this repository includes an installable skill under [`skills/lkr-code-mode`](./skills/lkr-code-mode) (and [`.agents/skills/lkr-code-mode`](./.agents/skills/lkr-code-mode)) that teaches agents how to work with the `lkr code-mode sandbox` non-interactively, including authentication options, CLI discovery commands, bundled helper scripts, and Looker SDK recipes.
156
+ For AI coding agents (Gemini CLI, Claude Code, Cursor, Copilot), this repository includes an installable skill under [skills/lkr-code-mode](./skills/lkr-code-mode) (and [.agents/skills/lkr-code-mode](./.agents/skills/lkr-code-mode)) for running `lkr code-mode sandbox` non-interactively, including auth flags, CLI discovery commands, helper scripts, and Looker SDK recipes.
132
157
 
133
- Install into your agent environment using `npx skills`:
158
+ Install it into your agent environment with `npx skills`:
134
159
 
135
160
  ```bash
136
161
  npx skills add lkrdev/cli --skill lkr-code-mode
137
162
  ```
138
163
 
139
- For detailed options, safe primitive transformations, MCP server configurations, and PKCE recovery, view the full [Code Mode Docs](./codemode.md).
164
+ For full options, MCP server configuration, and PKCE recovery, see the [Code Mode docs](./codemode.md).
140
165
 
141
166
  ## MCP
142
167
  Built into the `lkr` is an MCP server. Right now its tools are based on helping you work within an IDE. To use it a tool like [Cursor](https://www.cursor.com/), add this to your mcp.json
@@ -257,7 +282,7 @@ This can also be used to stress test your Looker environment as it serves an API
257
282
  ## User Attribute Updater (OIDC Token)
258
283
 
259
284
  1. Create a new cloud run using the `lkr-cli` public docker image `us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest`
260
- 2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings. See example [`gcloud` command](#example-gcloud-command)
285
+ 2. Put in the environment variables LOOKERSDK_CLIENT_ID, LOOKERSDK_CLIENT_SECRET, LOOKERSDK_BASE_URL, LOOKER_WHITELISTED_BASE_URLS. The `LOOKER_WHITELISTED_BASE_URLS` would be the same url as the `LOOKERSDK_BASE_URL` if you are only using this for a single Looker instance. For more advanced use cases, you can set the `LOOKER_WHITELISTED_BASE_URLS` to a comma separated list of urls. The body of the request also accepts a `base_url`, `client_id`, and `client_secret` key that will override these settings. See example [gcloud command](#example-gcloud-command)
261
286
  3. For the command and arguments use:
262
287
  - command: `lkr`
263
288
  - args: `tools` `user-attribute-updater`
@@ -313,21 +338,21 @@ gcloud run deploy lkr-access-token-updater \
313
338
  --set-env-vars LOOKERSDK_CLIENT_ID=<your client id>,LOOKERSDK_CLIENT_SECRET=<your client secret>,LOOKERSDK_BASE_URL=<your instance url>,LOOKER_WHITELISTED_BASE_URLS=<your instance url>
314
339
  ```
315
340
 
316
- ## Python SDK & Library Usage
341
+ ## Python SDK and library usage
317
342
 
318
343
  When installing `lkr-dev-cli` in your Python environment, you can import tools and pre-authenticated Looker SDK clients directly into your scripts, apps, or Jupyter notebooks.
319
344
 
320
- ### Package Import Aliases (`lkr` vs `lkr_dev_cli`)
321
- To maximize convenience and match user intuition, both `lkr` and `lkr_dev_cli` are available as identical top-level Python packages. You can use them completely interchangeably:
345
+ ### Package import aliases (`lkr` vs `lkr_dev_cli`)
346
+ Both `lkr` and `lkr_dev_cli` are exported as identical top-level Python packages:
322
347
 
323
348
  ```python
324
349
  from lkr import init_sdk, UserAttributeUpdater
325
- # works exactly identical to:
350
+ # works the same as:
326
351
  from lkr_dev_cli import init_sdk, UserAttributeUpdater
327
352
  ```
328
353
 
329
354
  ### Initializing the Looker SDK (`init_sdk`)
330
- The `init_sdk()` function initializes and returns an authenticated `ExtendedLooker40SDK` instance. It automatically handles credential discovery and authentication:
355
+ `init_sdk()` returns an authenticated `ExtendedLooker40SDK` instance and handles credential discovery automatically:
331
356
 
332
357
  ```python
333
358
  from lkr_dev_cli import init_sdk
@@ -373,7 +398,7 @@ It can also support looking up looker ids. It will lookup the following if the i
373
398
  - group_id by the name
374
399
 
375
400
 
376
- ### Example Usage
401
+ ### Example usage
377
402
 
378
403
  ```python
379
404
  from lkr import UserAttributeUpdater
@@ -431,49 +456,110 @@ def delete_user_attribute(user_attribute_name: str, email: str):
431
456
  email=email,
432
457
  )
433
458
  updater.delete_user_attribute_value()
459
+ ```
434
460
 
435
- ## Permission Deprecation Tool
461
+ ## Permission deprecation tool
436
462
 
437
- The `schedule-download-deprecation` tool helps Looker admins ensure that users do not lose access to models they already have when Looker moves towards more granular model-specific permissions for scheduling and downloading.
463
+ The `schedule-download-deprecation` tool helps Looker admins check that users do not lose access to models they already use when Looker moves to model-specific permissions for scheduling and downloading.
438
464
 
439
465
  ### How it helps
440
- Currently, some permissions in Looker can be granted instance-wide. In the future, these permissions may need to be explicitly granted at the model level (via Model Sets). This tool audits all active users and identifies those who:
441
- - Have "target permissions" (like `download_with_limit`, `schedule_look_emails`, etc.) instance-wide.
442
- - Do **not** have those same permissions for specific models they otherwise have access to.
466
+ Some permissions in Looker are currently granted instance-wide, and in the future may need to be granted at the model level via Model Sets. This tool audits active users and finds those who:
467
+ - Have target permissions (like `download_with_limit`, `schedule_look_emails`, etc.) instance-wide.
468
+ - Do not have those same permissions for specific models they otherwise have access to.
443
469
 
444
- By running this tool, an admin can proactively identify and fix permission gaps before any deprecation takes effect, ensuring a seamless experience for end-users.
470
+ Admins can run this before deprecation takes effect to find and fix permission gaps.
445
471
 
446
472
  ### Usage
447
- This command should be run by a **Looker Admin**.
473
+ Run this command as a Looker Admin:
448
474
 
449
475
  ```bash
450
476
  uvx lkr-dev-cli[all] tools schedule-download-deprecation
451
477
  ```
452
478
 
453
479
  Options:
454
- - `--csv`: Export the results to a CSV file for easier analysis of large instances.
455
- - `--unfiltered`: Show all users, including those who have all required permissions across all models.
456
- - `--model-offset`: Slice the table output to show different sets of models (the table shows 5 models at a time).
480
+ - `--csv` exports the results to a CSV file for large instances.
481
+ - `--unfiltered` shows all users, including those who already have all required permissions across all models.
482
+ - `--model-offset` slices the table output to show different sets of models (the table shows 5 models at a time).
483
+
484
+
485
+ ## Gemini Enterprise agents (`lkr tools agents`)
486
+
487
+ Looker's UI only supports connecting one default Gemini Enterprise (Discovery Engine) app per Looker instance. `lkr tools agents` lets you publish, list, and delete Looker Conversational Analytics (CA) agents across multiple Gemini Enterprise apps, GCP projects, and locations (`global`, `us`, `eu`).
488
+
489
+ For all flags and options, see the [lkr tools agents CLI docs](./lkr.md#lkr-tools-agents) ([publish](./lkr.md#lkr-tools-agents-publish), [list](./lkr.md#lkr-tools-agents-list), [delete](./lkr.md#lkr-tools-agents-delete)).
490
+
491
+ > [!IMPORTANT]
492
+ > Before publishing an agent, make sure **Admin > Gemini in Looker > Publish to Gemini Enterprise** is enabled on your Looker instance, and that the Looker service account has IAM permissions (Discovery Engine Admin) on the target GCP project plus a Gemini Enterprise user license in **Gemini Enterprise > Manage Users** (or "Assign licenses automatically" enabled on the app).
493
+
494
+ ### Finding your agent ID
495
+
496
+ To get an agent's `<agent_id>` in the Looker UI:
497
+ 1. Open **Conversational Analytics** from the left navigation menu and click **Manage Agents** (or go to `https://<your-looker-instance>/conversations/agents`).
498
+ 2. Click on the agent (or select **Edit** from its menu).
499
+ 3. Copy the `<agent_id>` GUID from the browser URL:
500
+ ```text
501
+ https://<your-looker-instance>/conversations/agents/<agent_id>
502
+ ```
503
+
504
+ ### Publishing an agent
505
+
506
+ ```bash
507
+ # Publish an agent to the Looker instance's default Gemini Enterprise app
508
+ uvx lkr-dev-cli tools agents publish <agent_id>
509
+
510
+ # Publish an agent to a specific (or secondary) Gemini Enterprise app
511
+ uvx lkr-dev-cli tools agents publish <agent_id> \
512
+ --project-number <gcp_project_number> \
513
+ --location global \
514
+ --engine-id <gemini_enterprise_engine_id> \
515
+ --validate
516
+ ```
517
+
518
+ ### Listing and reconciling published agents
519
+
520
+ `lkr tools agents list` merges records from the Looker artifact store, live Discovery Engine A2A agent cards (when `--gcp-token` is passed), and Looker's default configuration. If an agent was deleted in the Gemini Enterprise UI, `list` updates its Looker artifact state to `unpublished` (pass `--no-update-artifact` to skip writing back to the artifact store).
521
+
522
+ ```bash
523
+ # List agents from Looker Artifacts and live Discovery Engine, and sync UI deletions back to Artifacts
524
+ uvx lkr-dev-cli tools agents list \
525
+ --project-number <gcp_project_number> \
526
+ --engine-id <gemini_enterprise_engine_id> \
527
+ --gcp-token $(gcloud auth print-access-token)
528
+ ```
529
+
530
+ ### Deleting or unpublishing an agent
531
+
532
+ ```bash
533
+ # Unpublish from the default Looker-configured Gemini Enterprise app
534
+ uvx lkr-dev-cli tools agents delete <agent_id>
535
+
536
+ # Delete from a secondary Gemini Enterprise app via Discovery Engine and update Looker Artifacts
537
+ uvx lkr-dev-cli tools agents delete <agent_id> \
538
+ --project-number <gcp_project_number> \
539
+ --location global \
540
+ --engine-id <gemini_enterprise_engine_id> \
541
+ --gcp-token $(gcloud auth print-access-token)
542
+ ```
457
543
 
458
544
 
459
- ## Optional Dependencies
545
+ ## Optional dependencies
460
546
 
461
- The `lkr` CLI supports optional dependencies that enable additional functionality. You can install these individually or all at once.
547
+ The `lkr` CLI has optional extras for specific commands. You can install them individually or all at once.
462
548
 
463
- ### Available Extras
549
+ ### Available extras
464
550
 
465
- - **`mcp`**: Enables the MCP (Model Context Protocol) server functionality and `lkr mcp` commands
466
- - **`observability`**: Enables the observability embed monitoring features and `lkr observability` commands
467
- - **`tools`**: Enables the user attribute updater functionality and `lkr tools` commands
551
+ - `mcp` enables the MCP (Model Context Protocol) server and `lkr mcp` commands.
552
+ - `observability` enables the embed monitoring server and `lkr observability` commands.
553
+ - `tools` enables the user attribute updater and `lkr tools` commands.
468
554
 
469
- ### Installing Optional Dependencies
555
+ ### Installing optional dependencies
470
556
 
471
- **Install all optional dependencies:**
557
+ Install all optional dependencies:
472
558
  ```bash
473
559
  uv sync --extra all
474
560
  ```
475
561
 
476
- **Install specific extras:**
562
+ Install specific extras:
477
563
  ```bash
478
564
  # Install MCP functionality
479
565
  uv sync --extra mcp
@@ -488,7 +574,7 @@ uv sync --extra user-attribute-updater
488
574
  uv sync --extra mcp --extra embed-observability
489
575
  ```
490
576
 
491
- **Using pip:**
577
+ Using pip:
492
578
  ```bash
493
579
  # Install all optional dependencies
494
580
  pip install lkr-dev-cli[all]