plugins/lisa-cursor/skills/lisa-setup-workstation/SKILL.md
Prepare a machine — a fresh laptop or a throwaway container — to run coding agents, before any repository exists. Detects which of Lisa's supported agents (Claude Code, Codex, Cursor, OpenCode, Antigravity, Copilot) are already installed, asks which credential manager the machine uses (Bitwarden, 1Password, Doppler, Vault, AWS, or none), and installs only what is missing, each by its vendor's own preferred method. Idempotent, headless by default, and emits a Dockerfile for a spin-up/spin-down environment. Run it on a new machine, in a container, or before cloning anything.
npx skillsauth add codyswanngt/lisa lisa-setup-workstationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
Security scan pending...
This skill is queued for security scanning. Results will appear when the scan completes.
Get a machine ready to run agents. No checkout required.
lisa-setup-local-env reads remoteEnv.tools — a project's declared toolchain — so it
needs a checkout to exist before it can answer anything. That leaves a gap at the start:
a bare laptop or an empty container has no repository yet, and therefore nothing to ask.
This skill fills that gap and stops there. It describes a machine, never a project:
workstation -> git clone -> lisa-detect-tooling -> lisa-setup-local-env
Project-scoped tools stay in remoteEnv.tools where they belong. Nothing here reads a
repository, and nothing here duplicates that manifest.
Start here — this is the entry point that presumes nothing:
npx -y @codyswann/lisa@latest workstation # report what is present and missing
npx -y @codyswann/lisa@latest workstation --install # install what is missing
That form needs only Node. No checkout, no agent, no Lisa install — npx resolves the package into its own cache.
Why it matters: this skill exists to prepare a machine with no coding agent and no checkout. But a skill can only be invoked by typing a slash command into an agent, and Lisa ships as a devDependency, so it does not exist until a repo is cloned and its dependencies installed. Both are exactly the state this is meant to create — so as a skill alone, the bootstrap was unreachable in the one scenario it was designed for. The CLI is the way in; the skill is the surface for people who already have an agent.
Every flag is the same either way:
lisa workstation --install --agents=claude,codex # only these agents
lisa workstation --provider=bitwarden # credential manager (asked if a TTY)
lisa workstation --json # machine-readable plan
lisa workstation --print-dockerfile # an image that runs this same script
Inside an agent, /lisa:setup:workstation runs the identical script; and the
script itself is directly runnable as node scripts/cli.mjs ….
Nothing is installed or written without --install. Exit status is non-zero when a required
tool is absent or an install fails, so this is usable as a gate.
There is no Docker branch anywhere in this skill. A container gets a throwaway $HOME and
dies with it; a laptop keeps its own. Same code path either way — so the rarely-run one
cannot rot, which is the failure mode a second install path eventually always has.
--print-dockerfile emits an image rather than shipping a committed one, so the image cannot
drift from the catalogue it provisions. It deliberately bakes in no repository: clone
inside the container, then run lisa-detect-tooling and lisa-setup-local-env for that
project's own tools.
node scripts/cli.mjs --print-dockerfile --agents=claude,codex --provider=bitwarden > Dockerfile
docker build -t lisa-workstation . && docker run --rm -it lisa-workstation
A tool present by any means is reported and left alone. That dissolves the "Homebrew or
~/.local/bin" question entirely: we never contend for ownership of a tool someone else's
package manager installed, and never shadow it with an earlier PATH entry that would silently
win over their upgrades. The report names where each tool came from so the operator can see
why it was skipped.
Running twice installs nothing the second time, and says so rather than going quiet — silence reads as "did nothing because it broke".
The obvious design — put every binary in ~/.local/bin so one code path serves a laptop and a
container alike — is wrong, and the agents show why:
claude -> ~/.local/share/claude/versions/2.1.221
cursor-agent -> ~/.local/share/cursor-agent/versions/2026.07.16-899851b
codex -> ~/.codex/packages/standalone/current/bin/codex
Each vendor manages its own version directory, and ~/.local/bin holds only a symlink.
Writing a raw binary there breaks the vendor's self-updater, which expects to swap a link
target and would instead find a real file in its way.
So each catalogue entry declares its own method, and the honest cost is recorded with it:
| kind | pinned | checksummed | notes |
| --- | --- | --- | --- |
| release-zip / release-tar | yes | yes | reuses the remote-env installer |
| npm-global | no | no | vendor registry |
| vendor-script | no | no | pipes a fetched script to a shell |
| manual | n/a | n/a | no headless installer published |
| required | n/a | n/a | expected from the OS or base image |
vendor-script is a real weakening of the guarantee assertPinned exists to provide, so the
report names every unchecksummed install rather than blending them in. Installing them
trusts the vendor's script at fetch time. The alternative — repackaging vendor binaries
ourselves — would break the self-updaters that own those directories.
lisa-secrets-access already treats the provider as an axis: Bitwarden, 1Password, Doppler,
Vault, AWS, or plain environment variables. A bootstrap that installed bws unconditionally
would contradict that — pushing every workstation onto one vendor and quietly making the
others second-class.
So the provider is a question, none is a first-class answer, and only the selected one is
installed. Installing all of them would leave four unused credential CLIs on the machine,
each an extra thing to keep patched for no benefit.
Headless is the primary mode, so with no TTY and no --provider, the answer is none — not
a prompt that would hang a container build forever. A misspelled provider stops the run
instead of falling back, because quietly provisioning the wrong credential manager is worse
than stopping.
--install.development
Prepare a machine — a fresh laptop or a throwaway container — to run coding agents, before any repository exists. Detects which of Lisa's supported agents (Claude Code, Codex, Cursor, OpenCode, Antigravity, Copilot) are already installed, asks which credential manager the machine uses (Bitwarden, 1Password, Doppler, Vault, AWS, or none), and installs only what is missing, each by its vendor's own preferred method. Idempotent, headless by default, and emits a Dockerfile for a spin-up/spin-down environment. Run it on a new machine, in a container, or before cloning anything.
tools
Provision and verify a remote execution environment for a host project — Codex Cloud today, other remote surfaces as they are added. Generates a repository-owned setup script that installs the declared toolchain, materializes secrets through lisa-secrets-access, and runs the project's own hook. Provisions by API where one exists, by driving the vendor console where one does not, and by emitting exact config otherwise — then proves the result with the same read-back regardless of which tier did the work. Use before dispatching any work with executionEnv.
tools
Bring a developer's machine in line with the toolchain the project declares. Reports every tool in remoteEnv.tools that is missing, outdated, or unpinned for this platform, and installs the missing ones into ~/.local/bin from the same pinned, checksummed entries the remote surfaces use — but only when asked. Same manifest, same pins, same installers as lisa-setup-remote-env; what differs is consent and that the pin is a floor rather than an equality. Run it on a fresh checkout, after a manifest change, or when a tool fails at the moment of use.
tools
Route one unit of work to a remote execution surface. Reads the executionEnv parameter (local by default, codex-cloud or claude-web today), verifies the environment is provisioned and bound to this repository, submits a thin skill invocation, records the task identifier to .lisa/remote-dispatch.json, and exits without polling. Routing only — the remote runs the identical skill from the identical repository. Composable and inline: other skills invoke it via the Skill tool rather than users calling it directly.