8000 feat(cli): lens ext lists, pulls, checks and pushes extension manifests by adeelahmad · Pull Request #563 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content

feat(cli): lens ext lists, pulls, checks and pushes extension manifests - #563

Merged
adeelahmad merged 9 commits into
mainfrom
claude/project-thread-k05fsx
Oct 18, 2026
Merged

adeelahmad merged 9 commits into
mainfrom
claude/project-thread-k05fsx

Conversation

@adeelahmad
@adeelahmad adeelahmad commented Oct 18, 2026 •
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: extensions' manifests went in and out one at a time, through the Extensions page or POST /api/v1/extensions, so keeping them in a git repository meant copying each by hand.

After: lens ext keeps them as files in a folder.

lens ext list                    # the extensions you can see; --json for scripts and agents
lens ext pull --dir extensions   # yours (admins: all); names or ids pick some, --all adds shared ones
lens ext check extensions        # check without saving; exits 1 when one doesn't check
lens ext push extensions         # changed ones become new versions, new ones extensions

With no address it works on this install's database as the first admin (or --as), like the other lens commands; with --url and --token (or LENS_URL, LENS_TOKEN) it works on any Lens server through the existing /api/v1/extensions routes.

How: app/cli_ext.py has two thin backends with the same six calls (list, get, check, create, save, share), one over the API with urllib, one calling extensions.py directly and auditing as the API does. A pulled file carries version: N (which check_manifest already ignores). A push refuses when the extension changed in Lens since that version, and a pull refuses to overwrite a file changed since it was pulled, each until --force. A push compares the file with Lens's manifest as read and, if they differ in form, as the check tidies both, so a hand-written file with defaults left out saves no empty versions. Two files with one name are both refused. visibility and namespaces in a file are applied on push; without them sharing is untouched.

Motivation and Context

The last open item of the assistant extensions work (DEVLOG 2026-10-03: "lens ext CLI (push/pull manifests)").

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change; ! in the title)

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (make hooks checks it on commit).
  • I added or updated tests: tests/api/test_cli_ext.py (this install's database, and a real HTTP server with editor and viewer tokens).
  • My change requires documentation updates, and I have updated docs/ accordingly: docs/assistant.md "Manifests as files: lens ext", docs/get-started.md, README, docs/requirements.md.
  • Users need more than the title to understand it, so I wrote it in changelog.d/lens-ext.md.

Done questions (AGENTS.md)

  • Goal: list, pull, push and check, as asked; merged on green CI. Local CI (ci/local-ci.sh: pre-commit, title, backend) passed on the first commit.
  • Agents: lens ext list --json, exit codes on every command, and everything it does is the existing API.
  • Zero setup: docker compose exec backend lens ext … works with no token; a remote server needs only an API token.
  • Fewest keystrokes: defaults to this folder and your own extensions; one command per folder.
  • Configurable: n/a, no new settings.
  • Light: standard library only (urllib), nothing new installed.
  • Private and secure: the remote path uses API tokens with their owner's rights; the local path is the database access every lens command has, audited with via: cli. File names come from extension names ([a-z][a-z0-9_]), so a pull can't write outside its folder. No new attack surface for threat-model.md.
  • Cost: n/a, no model calls (checking an MCP server lists its tools, as the API check already does).
  • User decides: nothing is overwritten on either side without --force; defaults unchanged.
  • Upgrades: n/a, no stored-data change.
  • Honest: README built list and requirements row name only what this PR adds.
  • Tests, docs and generated files updated (no API change, so no make openapi).
  • Open standards: manifests stay YAML and Markdown with frontmatter; no new dependencies.
  • Reported with evidence. Refine later: pull doesn't write sharing into files, deleting an extension isn't a push (removing its file does nothing), and a real MCP token typed into a file makes every push save a version, since Lens shows it as ••••.
  • Reuse: parse_manifest, check_manifest, to_manifest, save_version and the existing routes; nothing reimplemented.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8

`lens ext pull` writes extensions' manifests into a folder, `push` saves the
changed ones as new versions and the new ones as extensions, `check` checks
them without saving, and `list` lists them (--json for agents). It works on
this install's database, as the first admin or --as, or on any Lens server
with --url and an API token. Pulled files carry `version: N`, so a push won't
save over changes made in Lens since, and a pull won't overwrite a file's own
changes, without --force.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8
@adeelahmad adeelahmad self-assigned this Oct 18, 2026
…#400 is released

Main's requirements check fails since v0.15.0 released #400 while the README
still listed it In progress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8
Copy link
Copy Markdown
Owner Author

Clicks failed on the phone only, in chat-research (added in #561): locator.waitFor: Timeout 60000ms exceeded while it waited for the Research plan card. The same journey passed on the computer in this same run (4 clicks, 34 keys). This PR changes no frontend code or chat code, only the lens ext command line, docs and the README lists, so the failure isn't from this diff. The runner pool is saturated right now (about ten PRs queued in Clicks after v0.15.0). I'm re-running the failed job once. If it fails again, I'll treat it as a real failure in the journey or the deep research flow on a phone and fix it.


Generated by Claude Code

@adeelahmad
adeelahmad merged commit eb7bf1f into main Oct 18, 2026
11 of 12 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-k05fsx branch October 18, 2026 11:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0