added gitea, n8n and invokeai MCP servers, plus docs/
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,25 @@ Docker scaffold for running Claude Code in an isolated container (see README.md)
|
||||
individual host files onto `~/.claude/.credentials.json` (the OAuth token)
|
||||
and `~/.claude.json` (account/onboarding state) — see `claudaris start`
|
||||
below for why these are per-file mounts rather than a directory volume.
|
||||
Three MCP servers for Claude Code are also installed at build time:
|
||||
`n8n-mcp` (npm, `/usr/local/bin/n8n-mcp`), the official `gitea-mcp`
|
||||
(latest release binary, `/usr/local/bin/gitea-mcp`), and
|
||||
`invokeai-mcp-server` (PyPI via `uv tool install`; upstream hardcodes the
|
||||
InvokeAI URL, so the Dockerfile sed-patches it to honor
|
||||
`$INVOKEAI_BASE_URL`, with a `grep` that fails the build if upstream
|
||||
changes and the patch stops landing). They're only *installed* by the
|
||||
Dockerfile — *registration* happens in `files/entrypoint.sh` on every
|
||||
container start (`claude mcp add --scope user`, skipped per-server if
|
||||
already present), because user-scope MCP config lives in `~/.claude.json`,
|
||||
which is bind-mounted from the host and would shadow anything registered
|
||||
at build time. Consequence of the "add if missing" guard: hand edits to a
|
||||
server's config survive restarts, but a server removed with
|
||||
`claude mcp remove` is re-added on the next container start. The servers
|
||||
read their instance URLs/tokens (`GITEA_HOST`, `GITEA_ACCESS_TOKEN`,
|
||||
`N8N_API_URL`, `N8N_API_KEY`, `INVOKEAI_BASE_URL`) from the environment
|
||||
Claude Code runs in — commented `export` templates live in
|
||||
`files/bash_aliases`, which is host-persisted, so tokens stay out of the
|
||||
image and the repo.
|
||||
`git config --system --add safe.directory '*'` is set so git works on
|
||||
`/projects` repos bind-mounted from the host (which the container, always
|
||||
running as root, would otherwise treat as untrusted). `files/entrypoint.sh`
|
||||
@@ -74,6 +93,11 @@ Docker scaffold for running Claude Code in an isolated container (see README.md)
|
||||
`bash_aliases` are also seeded onto the host by `claudaris start` so their
|
||||
bind-mounted copies can diverge without a rebuild.
|
||||
- `README.md` — usage instructions.
|
||||
- `docs/` — user documentation in markdown: `README.md` (index),
|
||||
`getting-started.md` (setup and daily use), `claudaris.md` (the executable,
|
||||
subcommand by subcommand, including the mount table), `mcp.md` (the baked-in
|
||||
MCP servers and their env vars). Keep these in sync when changing the
|
||||
script, Dockerfile, or entrypoint.
|
||||
|
||||
## Common commands
|
||||
```bash
|
||||
|
||||
+26
@@ -56,6 +56,32 @@ RUN curl -fsSL https://claude.ai/install.sh | bash
|
||||
RUN PATH="/root/.local/bin:$PATH" bash -c \
|
||||
'curl -fsSL https://raw.githubusercontent.com/leeguooooo/claude-code-usage-bar/main/web-install.sh | bash'
|
||||
|
||||
# MCP servers for Claude Code. Only installed here — they're registered at
|
||||
# user scope by entrypoint.sh on container start, because user-scope MCP
|
||||
# config lives in ~/.claude.json, which is bind-mounted from the host and
|
||||
# would shadow anything written to it at build time. Each server picks up
|
||||
# its instance URL/token from the environment (see files/bash_aliases).
|
||||
|
||||
# n8n — https://github.com/czlonkowski/n8n-mcp
|
||||
RUN npm install -g --prefix /usr/local n8n-mcp
|
||||
|
||||
# Gitea — official server, latest release binary
|
||||
# https://gitea.com/gitea/gitea-mcp
|
||||
RUN tag="$(curl -fsSL https://gitea.com/api/v1/repos/gitea/gitea-mcp/releases/latest \
|
||||
| python -c 'import json,sys; print(json.load(sys.stdin)["tag_name"])')" && \
|
||||
curl -fsSL "https://gitea.com/gitea/gitea-mcp/releases/download/${tag}/gitea-mcp_Linux_x86_64.tar.gz" \
|
||||
| tar -xz -C /usr/local/bin gitea-mcp && \
|
||||
chmod 755 /usr/local/bin/gitea-mcp
|
||||
|
||||
# InvokeAI — https://github.com/coinstax/invokeai-mcp-server. Upstream
|
||||
# hardcodes the InvokeAI URL, so patch it to honor $INVOKEAI_BASE_URL; the
|
||||
# grep fails the build if upstream changes shape and the patch stops landing.
|
||||
RUN uv tool install invokeai-mcp-server && \
|
||||
sed -i 's|^INVOKEAI_BASE_URL = .*|import os\nINVOKEAI_BASE_URL = os.environ.get("INVOKEAI_BASE_URL", "http://127.0.0.1:9090")|' \
|
||||
/root/.local/share/uv/tools/invokeai-mcp-server/lib/python*/site-packages/invokeai_mcp_server.py && \
|
||||
grep -q 'INVOKEAI_BASE_URL = os.environ.get' \
|
||||
/root/.local/share/uv/tools/invokeai-mcp-server/lib/python*/site-packages/invokeai_mcp_server.py
|
||||
|
||||
# tmux wrapper
|
||||
COPY files/tmux /usr/local/bin/tmux
|
||||
COPY files/tmux.conf /etc/tmux.conf
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
Claudaris (klaw-DAR-iss): A moveable docker container for Claude code. using Arch btw.
|
||||
|
||||
Full documentation lives in [`docs/`](docs/README.md): [getting started](docs/getting-started.md),
|
||||
the [`claudaris` executable](docs/claudaris.md), and [MCP servers](docs/mcp.md).
|
||||
|
||||
## Configure
|
||||
|
||||
Run the interactive wizard and answer its prompts (press enter to keep a
|
||||
@@ -49,6 +52,21 @@ To let the container SSH out to other machines, create `$DATA_DIR/ssh`
|
||||
on the host and populate it with keys/config *before* running `./claudaris start`. If
|
||||
present, it's bind-mounted read-only to `/root/.ssh`. It's off by default.
|
||||
|
||||
## MCP servers
|
||||
|
||||
MCP servers for [Gitea](https://gitea.com/gitea/gitea-mcp),
|
||||
[n8n](https://github.com/czlonkowski/n8n-mcp), and
|
||||
[InvokeAI](https://github.com/coinstax/invokeai-mcp-server) are baked into
|
||||
the image and registered with Claude Code (user scope) automatically on
|
||||
container start. To point them at your instances, uncomment and fill in the
|
||||
`export` lines at the bottom of your host-persisted
|
||||
`$DATA_DIR/home/bash_aliases` (`GITEA_HOST`, `GITEA_ACCESS_TOKEN`,
|
||||
`N8N_API_URL`, `N8N_API_KEY`, `INVOKEAI_BASE_URL`) — if yours was seeded
|
||||
before this feature existed, copy the block from `files/bash_aliases`.
|
||||
Tokens stay on the host, out of the image and repo. Note the services run
|
||||
elsewhere (not in this container), so use URLs reachable from inside it —
|
||||
`127.0.0.1` here means the container itself.
|
||||
|
||||
## Notes
|
||||
|
||||
Claude Code is installed at build time under `/root`, so a rebuild always
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# claudaris docs
|
||||
|
||||
Claudaris (klaw-DAR-iss) is a movable Docker container for running
|
||||
[Claude Code](https://code.claude.com/docs) in isolation, built on Arch Linux.
|
||||
Your login, dotfiles, and MCP configuration live on the host, so the image can
|
||||
be rebuilt at any time (always pulling the latest Claude Code release) without
|
||||
losing anything.
|
||||
|
||||
- **[Getting started](getting-started.md)** — prerequisites, first-time setup,
|
||||
and daily use.
|
||||
- **[The `claudaris` executable](claudaris.md)** — every subcommand, what it
|
||||
does, and the files and mounts behind it.
|
||||
- **[MCP servers](mcp.md)** — the Gitea, n8n, and InvokeAI MCP servers baked
|
||||
into the image, and how to point them at your instances.
|
||||
@@ -0,0 +1,96 @@
|
||||
# The `claudaris` executable
|
||||
|
||||
`./claudaris` is a single bash script at the repo root that wraps every
|
||||
Docker operation. It `cd`s to its own directory first, so it can be invoked
|
||||
from anywhere. Run it with no arguments (or `help`) for usage.
|
||||
|
||||
```
|
||||
Usage: ./claudaris <command>
|
||||
|
||||
Commands:
|
||||
config, configure Interactive wizard to write .env with your settings
|
||||
build Build the container image (always --no-cache --pull)
|
||||
start Start (or create) the container
|
||||
connect Start the container if needed, then attach a tmux session
|
||||
remove, stop, rm Stop and remove the container
|
||||
help Show this message
|
||||
```
|
||||
|
||||
All commands source `.env` if present (gitignored, written by `config`),
|
||||
falling back to `NAME=claudaris` and the defaults listed below.
|
||||
|
||||
## `config` (alias: `configure`)
|
||||
|
||||
Interactive wizard: prompts for `NAME`, `DATA_DIR`, and `WORKSPACE_DIR`,
|
||||
showing the current/default value for each (enter keeps it), then writes all
|
||||
three to `.env`. Safe to re-run any time. See
|
||||
[Getting started](getting-started.md#1-configure) for what each variable
|
||||
means.
|
||||
|
||||
## `build`
|
||||
|
||||
```bash
|
||||
sudo ./claudaris build
|
||||
```
|
||||
|
||||
Runs `docker build --no-cache --pull -t "$NAME" .`. Always uncached so a
|
||||
rebuild picks up the latest Arch packages, the latest Claude Code release
|
||||
(installed straight into `/root` in the image), and the latest
|
||||
[MCP server](mcp.md) releases.
|
||||
|
||||
## `start`
|
||||
|
||||
Creates and starts the container — or just `docker start`s it if a container
|
||||
named `$NAME` already exists (in that case none of the mount setup below is
|
||||
re-evaluated; use `remove` first to pick up mount changes).
|
||||
|
||||
On the host side it first seeds, without overwriting anything that already
|
||||
exists:
|
||||
|
||||
- `$DATA_DIR/home/.bashrc` and `$DATA_DIR/home/bash_aliases` — copied from
|
||||
`files/bashrc` and `files/bash_aliases`.
|
||||
- `$DATA_DIR/claude/credentials.json` and `$DATA_DIR/claude/claude.json` —
|
||||
created empty. Seeding them as files matters: if Docker had to create the
|
||||
mount targets itself it would make directories, breaking the login mounts.
|
||||
|
||||
Then it runs the container with:
|
||||
|
||||
| Mount / flag | Purpose |
|
||||
| --- | --- |
|
||||
| `--name "$NAME" --hostname "$NAME"` | Prompt reads `root@$NAME` instead of a random container ID. |
|
||||
| `$DATA_DIR/home/.bashrc` → `/root/.bashrc` | Per-host shell config, editable without a rebuild. |
|
||||
| `$DATA_DIR/home/bash_aliases` → `/opt/dotfiles/bash_aliases` | Per-host aliases and [MCP env vars](mcp.md); sourced by `.bashrc`. |
|
||||
| `$DATA_DIR/claude/credentials.json` → `/root/.claude/.credentials.json` | Claude Code OAuth token. |
|
||||
| `$DATA_DIR/claude/claude.json` → `/root/.claude.json` | Claude Code account/onboarding state and user-scope MCP config. |
|
||||
| `$WORKSPACE_DIR` → `/projects` | Your project workspace. |
|
||||
| `$DATA_DIR/ssh` → `/root/.ssh` (read-only, only if the host dir exists) | Opt-in SSH access to other machines. |
|
||||
|
||||
The login files are individual file mounts rather than a directory volume on
|
||||
purpose: Claude Code saves them atomically (write a temp file, then
|
||||
`rename()` over the target), and `rename()` onto a symlink replaces the
|
||||
symlink instead of writing through it — which would silently break
|
||||
persistence. A bind mount doesn't have that failure mode.
|
||||
|
||||
## `connect`
|
||||
|
||||
```bash
|
||||
sudo ./claudaris connect
|
||||
```
|
||||
|
||||
Runs `docker start "$NAME"` (a no-op if already running) and then
|
||||
`docker exec -it "$NAME" tmux`. The in-container `tmux` is a wrapper that
|
||||
attaches to the `main` session if it exists and creates it otherwise, so
|
||||
`connect` always lands you in the same session.
|
||||
|
||||
The explicit `docker start` matters because the container stops itself: the
|
||||
entrypoint creates the `main` tmux session and exits once that session ends
|
||||
(tmux defaults — a window closes when its shell exits, the session closes
|
||||
with its last window). There's no `--restart` policy, so after a Ctrl+D the
|
||||
container sits stopped until `connect` (or `start`) brings it back.
|
||||
|
||||
## `remove` (aliases: `stop`, `rm`)
|
||||
|
||||
Stops (ignoring errors if already stopped) and removes the container, so the
|
||||
next `start` recreates it fresh — needed after a `build` to actually run the
|
||||
new image, or after changing mounts. Nothing under `$DATA_DIR` or
|
||||
`$WORKSPACE_DIR` is touched.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Getting started
|
||||
|
||||
Claudaris runs Claude Code inside an Arch Linux container, with your project
|
||||
workspace bind-mounted in and your login persisted on the host. Everything is
|
||||
driven by the [`./claudaris` executable](claudaris.md) at the repo root.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker installed and running on the host.
|
||||
- Root (or equivalent Docker) access — the examples below use `sudo`.
|
||||
- A Claude account to log in with on first run.
|
||||
|
||||
## 1. Configure
|
||||
|
||||
From the repo root, run the interactive wizard and answer its prompts
|
||||
(press enter to keep a default):
|
||||
|
||||
```bash
|
||||
./claudaris config
|
||||
```
|
||||
|
||||
It asks for three values and writes them to `.env` (gitignored — every user
|
||||
of a shared checkout keeps their own):
|
||||
|
||||
| Variable | Default | Meaning |
|
||||
| --------------- | ---------------------- | -------------------------------------------------------------- |
|
||||
| `NAME` | `claudaris` | Image *and* container name. Pick something unique to you (e.g. `chris-claude`) if several people run containers from the same repo checkout. |
|
||||
| `DATA_DIR` | `/data/$NAME` | Host directory for everything that must survive rebuilds: dotfiles, Claude login, optional SSH keys. |
|
||||
| `WORKSPACE_DIR` | `/home/$USER/projects` | Host directory mounted as `/projects` inside the container — this is where Claude Code works. |
|
||||
|
||||
Re-run `config` any time to change these.
|
||||
|
||||
## 2. Build the image
|
||||
|
||||
```bash
|
||||
sudo ./claudaris build
|
||||
```
|
||||
|
||||
The build always runs with `--no-cache --pull`, so every rebuild picks up the
|
||||
latest Arch packages and the latest Claude Code release. Claude Code is
|
||||
installed into the image itself (not a volume) — rebuilding is how you
|
||||
upgrade it.
|
||||
|
||||
## 3. Start and connect
|
||||
|
||||
```bash
|
||||
sudo ./claudaris start
|
||||
sudo ./claudaris connect
|
||||
```
|
||||
|
||||
`start` creates the container (seeding host-side copies of the dotfiles and
|
||||
login files on first run); `connect` attaches you to its tmux session. You
|
||||
land in a shell at `/projects` as `root@$NAME`.
|
||||
|
||||
On first connect, run `claude` and log in. The two files that carry the login
|
||||
(`~/.claude/.credentials.json` and `~/.claude.json`) are bind-mounted from
|
||||
`$DATA_DIR/claude/` on the host, so you stay logged in across container
|
||||
rebuilds and re-creations.
|
||||
|
||||
## 4. Daily use
|
||||
|
||||
- **Attach:** `sudo ./claudaris connect` — also restarts the container if it
|
||||
stopped. The container exits on its own when the tmux session ends (last
|
||||
shell exits via Ctrl+D, `exit`, or a crash); there is no Docker restart
|
||||
policy, so `connect` bringing it back up is the normal flow.
|
||||
- **Detach without stopping anything:** standard tmux detach
|
||||
(`Ctrl+b d`).
|
||||
- **Upgrade Claude Code / packages:** `sudo ./claudaris remove`, then
|
||||
`sudo ./claudaris build` and `sudo ./claudaris start`. Login, dotfiles, and
|
||||
MCP registration all survive this.
|
||||
|
||||
## Customizing your shell
|
||||
|
||||
`~/.bashrc` and the aliases file are bind-mounted single files living at
|
||||
`$DATA_DIR/home/.bashrc` and `$DATA_DIR/home/bash_aliases` on the host. Edit
|
||||
them there (or inside the container) and the changes persist across rebuilds —
|
||||
no image change needed. They're seeded from `files/bashrc` and
|
||||
`files/bash_aliases` the first time `start` runs and never overwritten after
|
||||
that.
|
||||
|
||||
This is also where you configure the [MCP servers](mcp.md): the bottom of
|
||||
`bash_aliases` has commented `export` lines for the Gitea/n8n/InvokeAI URLs
|
||||
and tokens.
|
||||
|
||||
## Optional: SSH access to other machines
|
||||
|
||||
To let the container SSH out, create `$DATA_DIR/ssh` on the host and populate
|
||||
it with keys/config *before* running `start`. If the directory exists, it's
|
||||
bind-mounted read-only at `/root/.ssh`. It's off by default.
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
# MCP servers
|
||||
|
||||
The image ships three [MCP](https://modelcontextprotocol.io/) servers for
|
||||
Claude Code, all speaking stdio:
|
||||
|
||||
| Server | Name in `/mcp` | What it gives Claude | Source |
|
||||
| --- | --- | --- | --- |
|
||||
| Gitea | `gitea` | Repos, issues, PRs, releases on your Gitea instance | [gitea/gitea-mcp](https://gitea.com/gitea/gitea-mcp) (official, latest release binary) |
|
||||
| n8n | `n8n` | n8n node documentation, plus workflow creation/management when the API env vars are set | [czlonkowski/n8n-mcp](https://github.com/czlonkowski/n8n-mcp) (npm) |
|
||||
| InvokeAI | `invokeai` | Text-to-image, img2img, and upscaling against your InvokeAI instance | [coinstax/invokeai-mcp-server](https://github.com/coinstax/invokeai-mcp-server) (PyPI) |
|
||||
|
||||
## How install and registration are split
|
||||
|
||||
The Dockerfile only *installs* the servers (`/usr/local/bin/n8n-mcp`,
|
||||
`/usr/local/bin/gitea-mcp`, and a `uv` tool venv for InvokeAI).
|
||||
*Registration* happens in `files/entrypoint.sh` on every container start,
|
||||
via `claude mcp add --scope user`.
|
||||
|
||||
It has to work that way: user-scope MCP config lives in `~/.claude.json`,
|
||||
which [`claudaris start`](claudaris.md#start) bind-mounts from the host — so
|
||||
anything registered at build time would be shadowed by the mounted file. The
|
||||
runtime registration writes into the mounted file instead, which also means
|
||||
it persists across rebuilds like the login does.
|
||||
|
||||
Registration is guarded per server: a server that's already present is left
|
||||
alone, so hand edits to its config survive restarts. The flip side is that a
|
||||
server deleted with `claude mcp remove` comes back on the next container
|
||||
start — to change one permanently, edit its entry rather than removing it.
|
||||
|
||||
## Pointing the servers at your instances
|
||||
|
||||
The servers read their URLs and tokens from the environment Claude Code runs
|
||||
in (Claude Code passes its environment through to stdio MCP servers). Set
|
||||
them in your host-persisted aliases file, `$DATA_DIR/home/bash_aliases`,
|
||||
where a commented template already exists at the bottom:
|
||||
|
||||
```bash
|
||||
export GITEA_HOST='https://gitea.example.com'
|
||||
export GITEA_ACCESS_TOKEN='...'
|
||||
export N8N_API_URL='https://n8n.example.com' # optional: enables workflow management tools
|
||||
export N8N_API_KEY='...'
|
||||
export INVOKEAI_BASE_URL='http://invokeai.example.com:9090'
|
||||
```
|
||||
|
||||
Then start a new shell (or `source ~/.bashrc`) and launch `claude`. Because
|
||||
the file lives on the host, tokens never end up in the image or the repo. If
|
||||
your `bash_aliases` was seeded before the MCP servers existed, copy the
|
||||
template block from `files/bash_aliases`.
|
||||
|
||||
Notes:
|
||||
|
||||
- **URLs must be reachable from inside the container.** `127.0.0.1` means
|
||||
the container itself, not the host. Use the host's LAN address or service
|
||||
hostname.
|
||||
- **Gitea:** create the token in Gitea under *Settings → Applications →
|
||||
Generate New Token*.
|
||||
- **n8n:** without `N8N_API_URL`/`N8N_API_KEY` the server still works as a
|
||||
node-documentation reference; the API pair unlocks creating and managing
|
||||
workflows. Create the key in n8n under *Settings → n8n API*.
|
||||
- **InvokeAI:** defaults to `http://127.0.0.1:9090` if unset. Upstream
|
||||
hardcodes that URL; the Dockerfile patches the package so
|
||||
`INVOKEAI_BASE_URL` is honored (and the build fails loudly if a future
|
||||
upstream release breaks the patch). Registration uses
|
||||
`python -m invokeai_mcp_server` because the package's console script is
|
||||
broken upstream.
|
||||
|
||||
## Checking it works
|
||||
|
||||
Inside the container:
|
||||
|
||||
```bash
|
||||
claude mcp list # all three should show as configured
|
||||
```
|
||||
|
||||
Or in a Claude Code session, run `/mcp` to see connection status, and try
|
||||
something like *"list my Gitea repos"*. A server whose env vars are unset
|
||||
will show as failed/erroring until you set them — the other servers are
|
||||
unaffected.
|
||||
+10
-1
@@ -23,4 +23,13 @@ alias tl='tmux list-sessions'
|
||||
alias gs='git status'
|
||||
|
||||
alias btw='fastfetch'
|
||||
alias cd='z'
|
||||
alias cd='z'
|
||||
|
||||
# MCP servers (see Dockerfile / entrypoint.sh). Uncomment and point at your
|
||||
# instances — Claude Code passes its environment through to the stdio
|
||||
# servers, so exporting these here is all the configuration they need.
|
||||
#export GITEA_HOST='https://gitea.example.com'
|
||||
#export GITEA_ACCESS_TOKEN='changeme'
|
||||
#export N8N_API_URL='https://n8n.example.com' # optional: enables workflow management tools
|
||||
#export N8N_API_KEY='changeme'
|
||||
#export INVOKEAI_BASE_URL='http://127.0.0.1:9090'
|
||||
@@ -5,6 +5,26 @@ set -euo pipefail
|
||||
# which bind-mounts ~/.claude/.credentials.json and ~/.claude.json individually
|
||||
# from the host (see claudaris) — nothing to seed or symlink here.
|
||||
|
||||
# Register the MCP servers baked into the image (see Dockerfile) at user
|
||||
# scope. Done here rather than at build time because user-scope MCP config
|
||||
# lives in ~/.claude.json, which is bind-mounted from the host. Each server
|
||||
# is only added if missing, so hand edits survive restarts — but a server
|
||||
# removed via `claude mcp remove` comes back on the next container start.
|
||||
[ -s /root/.claude.json ] || echo '{}' > /root/.claude.json
|
||||
register_mcp() {
|
||||
local name="$1"; shift
|
||||
/root/.local/bin/claude mcp get "$name" >/dev/null 2>&1 ||
|
||||
/root/.local/bin/claude mcp add --scope user "$name" "$@" || true
|
||||
}
|
||||
register_mcp gitea -- /usr/local/bin/gitea-mcp -t stdio
|
||||
register_mcp n8n --env MCP_MODE=stdio --env LOG_LEVEL=error \
|
||||
--env DISABLE_CONSOLE_OUTPUT=true -- /usr/local/bin/n8n-mcp
|
||||
# Not the `invokeai-mcp-server` console script — it's broken upstream
|
||||
# (calls the async main() without asyncio.run); `python -m` is the
|
||||
# invocation upstream documents.
|
||||
register_mcp invokeai -- \
|
||||
/root/.local/share/uv/tools/invokeai-mcp-server/bin/python -m invokeai_mcp_server
|
||||
|
||||
# Create the main tmux session if it does not exist.
|
||||
/usr/bin/tmux new-session -d -s main 2>/dev/null || true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user