lkr-dev-cli 0.0.53__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 (117) hide show
  1. {lkr_dev_cli-0.0.53 → 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.53/README.md → lkr_dev_cli-0.0.57/PKG-INFO +161 -36
  7. lkr_dev_cli-0.0.53/PKG-INFO → lkr_dev_cli-0.0.57/README.md +117 -72
  8. lkr_dev_cli-0.0.57/TODO.md +33 -0
  9. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/main.py +29 -26
  10. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/swagger.json +3072 -2056
  11. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/__init__.py +2 -0
  12. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/classes.py +30 -1
  13. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/extended_sdk_methods/main.py +132 -0
  14. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/main.py +11 -3
  15. lkr_dev_cli-0.0.57/lkr/parse/__init__.py +167 -0
  16. lkr_dev_cli-0.0.57/lkr/parse/constants.py +252 -0
  17. lkr_dev_cli-0.0.57/lkr/parse/dag.py +271 -0
  18. lkr_dev_cli-0.0.57/lkr/parse/lookml.py +704 -0
  19. lkr_dev_cli-0.0.57/lkr/parse/lookml_to_api.py +1643 -0
  20. lkr_dev_cli-0.0.57/lkr/parse/main.py +270 -0
  21. lkr_dev_cli-0.0.57/lkr/parse/sql.py +243 -0
  22. lkr_dev_cli-0.0.57/lkr/parse/sql_to_lookml.py +991 -0
  23. lkr_dev_cli-0.0.57/lkr/parse/types.py +324 -0
  24. lkr_dev_cli-0.0.57/lkr/schema/__init__.py +15 -0
  25. lkr_dev_cli-0.0.57/lkr/schema/_schema_rs.so +0 -0
  26. lkr_dev_cli-0.0.57/lkr/schema/builder.py +163 -0
  27. lkr_dev_cli-0.0.57/lkr/schema/dynamic_fields.py +113 -0
  28. lkr_dev_cli-0.0.57/lkr/schema/fields.py +119 -0
  29. lkr_dev_cli-0.0.57/lkr/schema/filter_expressions.py +242 -0
  30. lkr_dev_cli-0.0.57/lkr/schema/main.py +202 -0
  31. lkr_dev_cli-0.0.57/lkr/schema/rust/Cargo.lock +345 -0
  32. lkr_dev_cli-0.0.57/lkr/schema/rust/Cargo.toml +25 -0
  33. lkr_dev_cli-0.0.57/lkr/schema/rust/src/lib.rs +1063 -0
  34. lkr_dev_cli-0.0.57/lkr/schema/validator.py +64 -0
  35. lkr_dev_cli-0.0.57/lkr/tools/agents.py +987 -0
  36. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/tools/main.py +2 -0
  37. lkr_dev_cli-0.0.57/lkr.md +524 -0
  38. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/pyproject.toml +21 -7
  39. lkr_dev_cli-0.0.57/scripts/schema/README.md +60 -0
  40. lkr_dev_cli-0.0.57/scripts/schema/__init__.py +1 -0
  41. lkr_dev_cli-0.0.57/scripts/schema/history.py +317 -0
  42. lkr_dev_cli-0.0.57/tests/test_agents_tools.py +469 -0
  43. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_dependency_resolution.py +3 -1
  44. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_extended_sdk_methods.py +88 -0
  45. lkr_dev_cli-0.0.57/tests/test_parse_lookml.py +1707 -0
  46. lkr_dev_cli-0.0.57/tests/test_parse_sql.py +101 -0
  47. lkr_dev_cli-0.0.57/tests/test_schema.py +857 -0
  48. lkr_dev_cli-0.0.57/uv.lock +2444 -0
  49. lkr_dev_cli-0.0.53/.gitignore +0 -5
  50. lkr_dev_cli-0.0.53/Makefile +0 -26
  51. lkr_dev_cli-0.0.53/lkr.md +0 -373
  52. lkr_dev_cli-0.0.53/uv.lock +0 -1912
  53. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/SKILL.md +0 -0
  54. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/examples.py +0 -0
  55. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/order_items_query.py +0 -0
  56. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/personal_folder_dashboards.py +0 -0
  57. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/readme.py +0 -0
  58. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-code-mode/scripts/traverse_folders.py +0 -0
  59. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/SKILL.md +0 -0
  60. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/bq_view_lookml_generator.py +0 -0
  61. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/configure_model.py +0 -0
  62. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/create_custom_view.py +0 -0
  63. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/deploy_and_reset_workspace.py +0 -0
  64. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/ensure_project_and_model.py +0 -0
  65. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/generate_lookml.py +0 -0
  66. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/init_project.py +0 -0
  67. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/inspect_connections.py +0 -0
  68. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/migrate_dashboard_to_udd.py +0 -0
  69. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/upload_assets.py +0 -0
  70. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.agents/skills/lkr-project-helper/scripts/validate_and_commit.py +0 -0
  71. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.github/workflows/release.yml +0 -0
  72. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.github/workflows/website.yml +0 -0
  73. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.python-version +0 -0
  74. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.vscode/launch.json +0 -0
  75. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/.vscode/settings.json +0 -0
  76. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/Dockerfile +0 -0
  77. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/LICENSE +0 -0
  78. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/cloudbuild.yaml +0 -0
  79. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/codemode.md +0 -0
  80. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/__init__.py +0 -0
  81. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/auth/__init__.py +0 -0
  82. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/auth/main.py +0 -0
  83. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/auth/oauth.py +0 -0
  84. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/auth_service.py +0 -0
  85. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/classes.py +0 -0
  86. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/LOCAL.md +0 -0
  87. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/__init__.py +0 -0
  88. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/constant.py +0 -0
  89. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/download_swagger.py +0 -0
  90. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/examples.py +0 -0
  91. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/help.py +0 -0
  92. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/readme.py +0 -0
  93. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/codemode/type.py +0 -0
  94. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/constants.py +0 -0
  95. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/custom_types.py +0 -0
  96. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/exceptions.py +0 -0
  97. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/logger.py +0 -0
  98. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/mcp/classes.py +0 -0
  99. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/mcp/main.py +0 -0
  100. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/mcp/utils.py +0 -0
  101. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/observability/classes.py +0 -0
  102. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/observability/embed_container.html +0 -0
  103. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/observability/main.py +0 -0
  104. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/observability/utils.py +0 -0
  105. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/tools/classes.py +0 -0
  106. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/tools/lookml.py +0 -0
  107. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr/tools/permission_deprecation.py +0 -0
  108. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/lkr_dev_cli/__init__.py +0 -0
  109. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/TESTING.md +0 -0
  110. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_codemode.py +0 -0
  111. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_deps.sh +0 -0
  112. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_init_sdk.py +0 -0
  113. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_lookml_tools.py +0 -0
  114. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_oauth_account.py +0 -0
  115. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_permission_deprecation.py +0 -0
  116. {lkr_dev_cli-0.0.53 → lkr_dev_cli-0.0.57}/tests/test_version.py +0 -0
  117. {lkr_dev_cli-0.0.53 → 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,12 +1,56 @@
1
+ Metadata-Version: 2.5
2
+ Name: lkr-dev-cli
3
+ Version: 0.0.57
4
+ Summary: lkr: a command line interface for looker
5
+ Author: bwebs
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.12
9
+ Requires-Dist: cryptography>=48.0.1
10
+ Requires-Dist: looker-sdk>=26.12.0
11
+ Requires-Dist: pydantic>=2.11.7
12
+ Requires-Dist: pydash>=8.0.5
13
+ Requires-Dist: questionary>=2.1.0
14
+ Requires-Dist: requests>=2.34.2
15
+ Requires-Dist: structlog>=25.4.0
16
+ Requires-Dist: typer>=0.16.0
17
+ Provides-Extra: all
18
+ Requires-Dist: duckdb>=1.3.1; extra == 'all'
19
+ Requires-Dist: fastapi[standard]>=0.136.3; extra == 'all'
20
+ Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'all'
21
+ Requires-Dist: nodejs-wheel>=24.19.0; extra == 'all'
22
+ Requires-Dist: pydantic-monty==0.0.23; extra == 'all'
23
+ Requires-Dist: selenium>=4.34.0; extra == 'all'
24
+ Requires-Dist: sqlglot>=30.19.0; extra == 'all'
25
+ Provides-Extra: code-mode
26
+ Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'code-mode'
27
+ Requires-Dist: pydantic-monty==0.0.23; extra == 'code-mode'
28
+ Provides-Extra: codemode
29
+ Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'codemode'
30
+ Requires-Dist: pydantic-monty==0.0.23; extra == 'codemode'
31
+ Provides-Extra: mcp
32
+ Requires-Dist: duckdb>=1.3.1; extra == 'mcp'
33
+ Requires-Dist: fastapi[standard]>=0.136.3; extra == 'mcp'
34
+ Requires-Dist: mcp[cli]<2,>=1.27.2; extra == 'mcp'
35
+ Provides-Extra: observability
36
+ Requires-Dist: fastapi[standard]>=0.136.3; extra == 'observability'
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'
41
+ Provides-Extra: tools
42
+ Requires-Dist: fastapi[standard]>=0.136.3; extra == 'tools'
43
+ Description-Content-Type: text/markdown
44
+
1
45
  # lkr cli
2
46
 
3
47
  The `lkr` cli is a tool for interacting with Looker. It combines Looker's SDK and customer logic to interact with Looker in meaninful ways. For a full list of commands, see the full [cli docs](./lkr.md)
4
48
 
5
49
  ## Usage
6
50
 
7
- `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`.
8
52
 
9
- 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>`.
10
54
 
11
55
  We also have a public docker image that you can use to run `lkr` commands.
12
56
 
@@ -14,6 +58,26 @@ We also have a public docker image that you can use to run `lkr` commands.
14
58
  docker run -it --rm us-central1-docker.pkg.dev/lkr-dev-production/lkr-cli/cli:latest lkr --help
15
59
  ```
16
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
+ ```
17
81
 
18
82
  ## Login
19
83
 
@@ -73,11 +137,11 @@ Go to the Looker API Explorer for Register OAuth App (https://your.looker.instan
73
137
  - This only needs to be done once per instance
74
138
 
75
139
 
76
- ## Code Mode
140
+ ## Code mode
77
141
 
78
- 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.
79
143
 
80
- ### Direct CLI Execution (Sandbox Mode)
144
+ ### Direct CLI execution (sandbox mode)
81
145
  Run scripts or inline code directly against your active Looker instance:
82
146
  ```bash
83
147
  # Execute inline Python code
@@ -87,17 +151,17 @@ uvx lkr-dev-cli code-mode sandbox --code="return me()"
87
151
  uvx lkr-dev-cli code-mode sandbox --file=./path/to/script.py
88
152
  ```
89
153
 
90
- ### Agent Skill (`lkr-code-mode`)
154
+ ### Agent skill (`lkr-code-mode`)
91
155
 
92
- 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.
93
157
 
94
- Install into your agent environment using `npx skills`:
158
+ Install it into your agent environment with `npx skills`:
95
159
 
96
160
  ```bash
97
161
  npx skills add lkrdev/cli --skill lkr-code-mode
98
162
  ```
99
163
 
100
- 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).
101
165
 
102
166
  ## MCP
103
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
@@ -218,7 +282,7 @@ This can also be used to stress test your Looker environment as it serves an API
218
282
  ## User Attribute Updater (OIDC Token)
219
283
 
220
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`
221
- 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)
222
286
  3. For the command and arguments use:
223
287
  - command: `lkr`
224
288
  - args: `tools` `user-attribute-updater`
@@ -274,21 +338,21 @@ gcloud run deploy lkr-access-token-updater \
274
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>
275
339
  ```
276
340
 
277
- ## Python SDK & Library Usage
341
+ ## Python SDK and library usage
278
342
 
279
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.
280
344
 
281
- ### Package Import Aliases (`lkr` vs `lkr_dev_cli`)
282
- 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:
283
347
 
284
348
  ```python
285
349
  from lkr import init_sdk, UserAttributeUpdater
286
- # works exactly identical to:
350
+ # works the same as:
287
351
  from lkr_dev_cli import init_sdk, UserAttributeUpdater
288
352
  ```
289
353
 
290
354
  ### Initializing the Looker SDK (`init_sdk`)
291
- 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:
292
356
 
293
357
  ```python
294
358
  from lkr_dev_cli import init_sdk
@@ -334,7 +398,7 @@ It can also support looking up looker ids. It will lookup the following if the i
334
398
  - group_id by the name
335
399
 
336
400
 
337
- ### Example Usage
401
+ ### Example usage
338
402
 
339
403
  ```python
340
404
  from lkr import UserAttributeUpdater
@@ -392,49 +456,110 @@ def delete_user_attribute(user_attribute_name: str, email: str):
392
456
  email=email,
393
457
  )
394
458
  updater.delete_user_attribute_value()
459
+ ```
395
460
 
396
- ## Permission Deprecation Tool
461
+ ## Permission deprecation tool
397
462
 
398
- 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.
399
464
 
400
465
  ### How it helps
401
- 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:
402
- - Have "target permissions" (like `download_with_limit`, `schedule_look_emails`, etc.) instance-wide.
403
- - 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.
404
469
 
405
- 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.
406
471
 
407
472
  ### Usage
408
- This command should be run by a **Looker Admin**.
473
+ Run this command as a Looker Admin:
409
474
 
410
475
  ```bash
411
476
  uvx lkr-dev-cli[all] tools schedule-download-deprecation
412
477
  ```
413
478
 
414
479
  Options:
415
- - `--csv`: Export the results to a CSV file for easier analysis of large instances.
416
- - `--unfiltered`: Show all users, including those who have all required permissions across all models.
417
- - `--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
+ ```
418
543
 
419
544
 
420
- ## Optional Dependencies
545
+ ## Optional dependencies
421
546
 
422
- 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.
423
548
 
424
- ### Available Extras
549
+ ### Available extras
425
550
 
426
- - **`mcp`**: Enables the MCP (Model Context Protocol) server functionality and `lkr mcp` commands
427
- - **`observability`**: Enables the observability embed monitoring features and `lkr observability` commands
428
- - **`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.
429
554
 
430
- ### Installing Optional Dependencies
555
+ ### Installing optional dependencies
431
556
 
432
- **Install all optional dependencies:**
557
+ Install all optional dependencies:
433
558
  ```bash
434
559
  uv sync --extra all
435
560
  ```
436
561
 
437
- **Install specific extras:**
562
+ Install specific extras:
438
563
  ```bash
439
564
  # Install MCP functionality
440
565
  uv sync --extra mcp
@@ -449,7 +574,7 @@ uv sync --extra user-attribute-updater
449
574
  uv sync --extra mcp --extra embed-observability
450
575
  ```
451
576
 
452
- **Using pip:**
577
+ Using pip:
453
578
  ```bash
454
579
  # Install all optional dependencies
455
580
  pip install lkr-dev-cli[all]