Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ wally shannon -- -u https://staging.example.com -r ./my-repo

Needs Docker and Node 18+. See [Shannon](docs/EDITORS.md#shannon).

**Scan repos you are authorised to test:**

```bash
wally deepsec -- init --repo ./my-repo
wally vvah -- scan --repo ./my-repo
```

DeepSec needs Node 18+ for `npx`. VVAH needs Python 3.11–3.14. See [Security tools](docs/EDITORS.md#security-tools).

**Get help:**

```bash
Expand Down
90 changes: 90 additions & 0 deletions docs/EDITORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ tool starts the way you already have it configured, and wally wires nothing.
| `prime-agent` | a temporary extension loaded with `-e` that registers the provider for the run, with the key in `RUNANYWHERE_API_KEY`; nothing enters `~/.prime/agent` |
| `command-code` | a `runanywhere-wally` provider merged into `~/.commandcode/providers.json` (it reads providers from nowhere else) and taken out when it exits: the original bytes go back if the file is unchanged, otherwise only that provider comes out. The file names `$WALLY_COMMAND_CODE_API_KEY` rather than holding the key. A local model, or a person with no Command Code sign-in, runs with `CMD_LOCAL_ONLY=1` (no Command Code gateway models, `/share`, `/usage` or server-side web tools); with no sign-in a placeholder `COMMAND_CODE_API_KEY` gets past Command Code's login screen. `--skip-onboarding --no-auto-update` are passed, `-t` is left to you. One run at a time (a lock in `~/.commandcode/`). Its own subcommands (`-- status`, `-- login`, …) run untouched; `-- acp` is wired, and there the editor picks the model |
| `shannon` | not a coding tool: it runs [Shannon](#shannon) on a model from your account. A `models.json` in your wally profile and `SHANNON_AI_MODEL` / `SHANNON_AI_API_KEY` in the child's environment only |
| `deepsec` | not a coding tool: it runs [DeepSec](#deepsec) on a hosted model from your account. Pi custom routing flags are injected for `init`, `setup`, `process` and `revalidate`; the API key is in `WALLY_DEEPSEC_API_KEY` for the child only |
| `vvah` | not a coding tool: it runs [VVAH](#vvah) on a hosted model from your account. A `config.local.yaml` names the model per role; `OPENAI_API_KEY` and `OPENAI_BASE_URL` are set for the child only |

Two flags go with `-m`. `--serve` holds the endpoint open and prints it instead
of launching anything, which is how a tool nobody has taught wally about gets
Expand Down Expand Up @@ -404,3 +406,91 @@ available to your account.

Some models need approval before an account can use them. If one is not on your
account's list, wally says so; request access in the console, then run again.

## Security tools

`wally deepsec` and `wally vvah` point open-source repo scanners at models on
your account. They are hosted-only: there is no local-model path. **Only scan
repos and systems you own or are explicitly authorised to test.**

Both need a signed-in account (`wally account login`), or a Cloud key from the
console. The key is never passed on the command line or written into config
files wally creates. For a run longer than a sign-in lasts, export a Cloud key
as `WALLY_CLOUD_KEY` before you start; wally reads it from the environment
only.

## DeepSec

[DeepSec](https://www.npmjs.com/package/deepsec) is an npm CLI wally does not
bundle. If `deepsec` is not on PATH, wally prints the `npx --yes deepsec@…`
command and asks before running it. Bare `wally deepsec` is DeepSec `init` in
the current directory: run it from a repo you own, not from `$HOME`. DeepSec
still links a Vercel project (Sandbox identity) even when models go through
your RunAnywhere account.

What you need:

- Node 18 or later (`npx`).
- A model on your account (`-m` or your default).

```bash
wally account login
wally deepsec -- init --repo ./my-repo
```

With no DeepSec command after `--`, wally runs `init`. Other subcommands pass
through unless they are `init`, `setup`, `process` or `revalidate`, which get
the hosted route:

```bash
wally deepsec -- status
wally deepsec -m glm-5.3-flash -- process
```

For those routed commands wally injects Pi-style flags ahead of yours:
`--agent pi`, `--model runanywhere/<id>` (Pi requires `provider/model`), `--model-auth custom`, `--ai-provider runanywhere`,
`--ai-base-url <console endpoint>`, `--ai-api-key-env WALLY_DEEPSEC_API_KEY`, and
`--ai-credential-header authorization:bearer`. It writes `models.json` under the
Wally profile and sets `PI_CODING_AGENT_DIR` plus `WALLY_DEEPSEC_API_KEY` for
DeepSec's process, and removes `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`,
`AI_GATEWAY_API_KEY` and `WALLY_CLOUD_KEY` from the child so nothing else can
override your key. Passing your own `--model-auth`, `--ai-base-url` or
`--ai-api-key-env` on those commands is refused.

## VVAH

[VVAH](https://github.com/visa/visa-vulnerability-agentic-harness) is a Python
CLI wally does not bundle. If `vvaharness` is missing, wally prints the install
command, asks `Install it now with \`…\`? [y/N]`, and on yes creates a venv
under the Wally profile (`<profile>/vvah/`) and pip-installs the pinned tag.

What you need:

- Python 3.11–3.14 on PATH (`python3.12` is preferred; Homebrew's `python3` is
often 3.15, which VVAH cannot install on). Checked after you confirm install.
- A model on your account (`-m` or your default).

```bash
wally account login
wally vvah
```

With no VVAH command after `--`, wally runs `scan --repo . --remediate`. Run
that from a project directory, not `$HOME` (the profile config lives under
`~/.config/wally`, and VVAH refuses a `--config` inside the scan target). Other

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This path is incorrect on Windows, where the VVAH profile is under %LOCALAPPDATA%/RunAnywhere/Wally. Refer to the platform-specific profile path instead of hardcoding ~/.config/wally.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/EDITORS.md, line 480:

<comment>This path is incorrect on Windows, where the VVAH profile is under `%LOCALAPPDATA%/RunAnywhere/Wally`. Refer to the platform-specific profile path instead of hardcoding `~/.config/wally`.</comment>

<file context>
@@ -404,3 +406,91 @@ available to your account.
+
+With no VVAH command after `--`, wally runs `scan --repo . --remediate`. Run
+that from a project directory, not `$HOME` (the profile config lives under
+`~/.config/wally`, and VVAH refuses a `--config` inside the scan target). Other
+commands pass through:
+
</file context>
Suggested change
`~/.config/wally`, and VVAH refuses a `--config` inside the scan target). Other
the active Wally profile (see the platform-specific paths above), and VVAH refuses a `--config` inside the scan target). Other

commands pass through:

```bash
wally vvah -- scan --repo ./my-repo
wally vvah -m glm-5.3-flash -- report
```

Each run rewrites `<profile>/vvah/config.local.yaml` (owner-only, 0600). Every

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This absolute path claim is not true for pass-through commands or targets containing the profile directory. Document that staging applies to routed commands and may use a temporary directory to keep the config outside the scan target.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/EDITORS.md, line 488:

<comment>This absolute path claim is not true for pass-through commands or targets containing the profile directory. Document that staging applies to routed commands and may use a temporary directory to keep the config outside the scan target.</comment>

<file context>
@@ -404,3 +406,91 @@ available to your account.
+wally vvah -m glm-5.3-flash -- report
+```
+
+Each run rewrites `<profile>/vvah/config.local.yaml` (owner-only, 0600). Every
+active scanner role maps to your chosen model with `via: openai`; the file
+never contains the API key. The child gets `OPENAI_API_KEY` and
</file context>
Suggested change
Each run rewrites `<profile>/vvah/config.local.yaml` (owner-only, 0600). Every
For each routed command, wally rewrites the overlay at `<profile>/vvah/config.local.yaml` (owner-only, 0600); if that path is inside the scan target, it uses a temporary directory instead. Every

active scanner role maps to your chosen model with `via: openai`; the file
never contains the API key. The child gets `OPENAI_API_KEY` and
`OPENAI_BASE_URL` only. VVAH's S10 stage can edit files on disk as part of a
scan; run it only on trees you are allowed to change.

If you confirm install and `python3` is missing or older than 3.11, wally

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This message is not emitted whenever python3 is missing or old; wally first selects any supported python3.11–python3.14 candidate. Describe the fallback message as applying only when no supported interpreter is available.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/EDITORS.md, line 494:

<comment>This message is not emitted whenever `python3` is missing or old; wally first selects any supported `python3.11`–`python3.14` candidate. Describe the fallback message as applying only when no supported interpreter is available.</comment>

<file context>
@@ -404,3 +406,91 @@ available to your account.
+`OPENAI_BASE_URL` only. VVAH's S10 stage can edit files on disk as part of a
+scan; run it only on trees you are allowed to change.
+
+If you confirm install and `python3` is missing or older than 3.11, wally
+prints `python 3.11 is not installed on this machine, Please install it first, Thank You`
+and exits. The venv is left in place for the next run.
</file context>
Suggested change
If you confirm install and `python3` is missing or older than 3.11, wally
If no supported Python 3.11–3.14 interpreter is available after you confirm install, wally reports the problem; for a missing or older-than-3.11 `python3`, it

prints `python 3.11 is not installed on this machine, Please install it first, Thank You`
and exits. The venv is left in place for the next run.
15 changes: 15 additions & 0 deletions skills/runanywhere/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@ sign-in lasts, the person exports a console Cloud key as `WALLY_CLOUD_KEY`.
Setup details, and how to point any other OpenAI-compatible tool at the
endpoint by hand, are in `docs/EDITORS.md`.

## Security tools

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The skill advertises no security-scanner trigger, so agents may not load these new DeepSec/VVAH instructions for security-tool requests. Add DeepSec/VVAH or authorised-repository scanning to the frontmatter description.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/runanywhere/SKILL.md, line 75:

<comment>The skill advertises no security-scanner trigger, so agents may not load these new DeepSec/VVAH instructions for security-tool requests. Add DeepSec/VVAH or authorised-repository scanning to the frontmatter description.</comment>

<file context>
@@ -72,6 +72,20 @@ sign-in lasts, the person exports a console Cloud key as `WALLY_CLOUD_KEY`.
 Setup details, and how to point any other OpenAI-compatible tool at the
 endpoint by hand, are in `docs/EDITORS.md`.
 
+## Security tools
+
+`wally deepsec` and `wally vvah` run hosted security scanners on a model from the
</file context>


`wally deepsec` and `wally vvah` run hosted security scanners on a model from the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: DeepSec and VVAH are local npm/Python scanners; only their model calls are hosted. Describe them as local security scanners against a hosted model so users understand the local execution and repository side effects.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/runanywhere/SKILL.md, line 77:

<comment>DeepSec and VVAH are local npm/Python scanners; only their model calls are hosted. Describe them as local security scanners against a hosted model so users understand the local execution and repository side effects.</comment>

<file context>
@@ -72,6 +72,20 @@ sign-in lasts, the person exports a console Cloud key as `WALLY_CLOUD_KEY`.
 
+## Security tools
+
+`wally deepsec` and `wally vvah` run hosted security scanners on a model from the
+person's account. Only suggest them for a repo or system they own or are
+authorised to test. DeepSec needs Node 18+; VVAH needs Python 3.11–3.14. Wally sets
</file context>
Suggested change
`wally deepsec` and `wally vvah` run hosted security scanners on a model from the
`wally deepsec` and `wally vvah` run local security scanners against a hosted model from the

person's account. Only suggest them for a repo or system they own or are
authorised to test. DeepSec needs Node 18+; VVAH needs Python 3.11–3.14. Wally sets
up routing and keys in the child environment, never on the command line. For a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The launcher passes DeepSec routing options on the command line, while it keeps the API key in the child environment. Say that keys stay out of command-line arguments instead of claiming routing never uses them.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/runanywhere/SKILL.md, line 80:

<comment>The launcher passes DeepSec routing options on the command line, while it keeps the API key in the child environment. Say that keys stay out of command-line arguments instead of claiming routing never uses them.</comment>

<file context>
@@ -72,6 +72,20 @@ sign-in lasts, the person exports a console Cloud key as `WALLY_CLOUD_KEY`.
+`wally deepsec` and `wally vvah` run hosted security scanners on a model from the
+person's account. Only suggest them for a repo or system they own or are
+authorised to test. DeepSec needs Node 18+; VVAH needs Python 3.11–3.14. Wally sets
+up routing and keys in the child environment, never on the command line. For a
+run longer than a sign-in lasts, they export a console Cloud key as
+`WALLY_CLOUD_KEY`. Details are in `docs/EDITORS.md`.
</file context>
Suggested change
up routing and keys in the child environment, never on the command line. For a
up each tool's route and keeps API keys out of command-line arguments. For a

run longer than a sign-in lasts, they export a console Cloud key as
`WALLY_CLOUD_KEY`. Details are in `docs/EDITORS.md`.

```bash
wally deepsec -- init --repo "$REPO_PATH"
wally vvah -- scan --repo "$REPO_PATH"
Comment on lines +85 to +86

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: These examples rely on an undefined $REPO_PATH, so copy-pasting them normally passes an empty repository path. Use a concrete placeholder such as ./my-repo, or define REPO_PATH immediately before the commands.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At skills/runanywhere/SKILL.md, line 85:

<comment>These examples rely on an undefined `$REPO_PATH`, so copy-pasting them normally passes an empty repository path. Use a concrete placeholder such as `./my-repo`, or define `REPO_PATH` immediately before the commands.</comment>

<file context>
@@ -72,6 +72,20 @@ sign-in lasts, the person exports a console Cloud key as `WALLY_CLOUD_KEY`.
+`WALLY_CLOUD_KEY`. Details are in `docs/EDITORS.md`.
+
+```bash
+wally deepsec -- init --repo "$REPO_PATH"
+wally vvah -- scan --repo "$REPO_PATH"
+```
</file context>
Suggested change
wally deepsec -- init --repo "$REPO_PATH"
wally vvah -- scan --repo "$REPO_PATH"
wally deepsec -- init --repo ./my-repo
wally vvah -- scan --repo ./my-repo

```

## Running a model directly

```bash
Expand Down Expand Up @@ -115,6 +129,7 @@ harness; those surfaces refuse it and point back here.
- **"not signed in"** — `wally account login`.
- **"not available on this account" or "not on your account's model list"** —
that model needs approval. Do not log in again; request access in the console.
- **DeepSec or VVAH prerequisites missing** — install Node 18+ (DeepSec) or Python 3.11–3.14 (VVAH); see `docs/EDITORS.md`.
- **"that key is not valid"** — the key was revoked or expired; `wally account login` again.
- **opencode not installed** — `npm i -g opencode-ai`.
- **a model is slow or unavailable** — `wally backends` shows which engines this
Expand Down
6 changes: 6 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ pub fn configure_app(app: &mut App) {
"shannon",
],
},
Section {
group: "Security tools",
names: &["deepsec", "vvah"],
},
Section {
group: "Account",
names: &["account"],
Expand Down Expand Up @@ -180,6 +184,8 @@ fn is_passthrough_command(token: &str) -> bool {
"prime-agent",
"command-code",
"shannon",
"deepsec",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: split_passthrough_argv now misclassifies a root option value such as --home deepsec or --home vvah as the wrapped command, inserting -- before the real subcommand. Restrict passthrough detection to the actual root subcommand position and skip root option values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/app.rs, line 187:

<comment>`split_passthrough_argv` now misclassifies a root option value such as `--home deepsec` or `--home vvah` as the wrapped command, inserting `--` before the real subcommand. Restrict passthrough detection to the actual root subcommand position and skip root option values.</comment>

<file context>
@@ -180,6 +184,8 @@ fn is_passthrough_command(token: &str) -> bool {
         "prime-agent",
         "command-code",
         "shannon",
+        "deepsec",
+        "vvah",
     ];
</file context>

"vvah",
];
NAMES.contains(&token)
}
Expand Down
6 changes: 6 additions & 0 deletions src/cli_formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,12 @@ mod tests {
"Open Command Code with a model",
"Coding tools",
),
leaf(
"deepsec",
"Scan your own repos with DeepSec",
"Security tools",
),
leaf("vvah", "Scan your own repos with VVAH", "Security tools"),
namespace(
"account",
"Account",
Expand Down
66 changes: 66 additions & 0 deletions src/commands/cmd_harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,72 @@ pub fn register_harness(app: &mut App) {
harness::shannon::launch(p.get_str("--model").as_deref(), &p.get_strs("args"))
});

let deepsec = app.add_subcommand("deepsec", "Scan your own repos with DeepSec");
deepsec.footer(&examples_footer(&[
Example::new(
"wally deepsec -- init --repo ./my-repo",
"Start a scan on a repo you are authorised to test (runs init)",
),
Example::new(
"wally deepsec -m glm-5.3-flash -- process",
"Choose the model",
),
Example::new(
"wally deepsec -- status",
"Other DeepSec commands pass through",
),
]));
deepsec.add_option(
"-m,--model",
ValueType::Text,
"A model from your account (default: your default model)",
);
deepsec
.add_option(
"args",
ValueType::Text,
"DeepSec's own command and options; with none, init",
)
.multi();
deepsec.prefix_command(true);
deepsec.callback(|p, _g| {
if harness::refuse_decisions_model(p.get_str("--model").as_deref()) {
return 2;
}
harness::deepsec::launch(p.get_str("--model").as_deref(), &p.get_strs("args"))
});

let vvah = app.add_subcommand("vvah", "Scan your own repos with VVAH");
vvah.footer(&examples_footer(&[
Example::new(
"wally vvah",
"Scan the current repo you are authorised to test",
),
Example::new(
"wally vvah -m glm-5.3-flash -- scan --repo ./my-repo",
"Scan another path with a chosen model",
),
Example::new("wally vvah -- report", "Other VVAH commands pass through"),
]));
vvah.add_option(
"-m,--model",
ValueType::Text,
"A model from your account (default: your default model)",
);
vvah.add_option(
"args",
ValueType::Text,
"VVAH's own command and options; with none, scan --repo . --remediate",
)
.multi();
vvah.prefix_command(true);
vvah.callback(|p, _g| {
if harness::refuse_decisions_model(p.get_str("--model").as_deref()) {
return 2;
}
harness::vvah::launch(p.get_str("--model").as_deref(), &p.get_strs("args"))
});

// The OpenAI-shaped agents, one subcommand per row of the table. They need
// no translator, so there is nothing here but resolving the model and
// handing the endpoint over the way each one takes it.
Expand Down
Loading