docs: add us-cpa openclaw installation guide

This commit is contained in:
Stefano Fiorini
2026-03-15 03:31:52 -05:00
parent 1be0317192
commit 9f650faf88
5 changed files with 93 additions and 1 deletions

View File

@@ -17,6 +17,35 @@ Without installing, the repo-local wrapper works directly:
skills/us-cpa/scripts/us-cpa --help
```
## OpenClaw installation
To install the skill for OpenClaw itself, copy the repo skill into the workspace skill directory and install its Python dependencies there.
1. Sync the repo copy into the workspace:
```bash
rsync -a --delete \
/Users/stefano/.openclaw/workspace/projects/stef-openclaw-skills/skills/us-cpa/ \
/Users/stefano/.openclaw/workspace/skills/us-cpa/
```
2. Create a workspace-local virtualenv and install the package:
```bash
cd /Users/stefano/.openclaw/workspace/skills/us-cpa
python3 -m venv .venv
. .venv/bin/activate
pip install -e .[dev]
```
3. Verify the installed workspace wrapper:
```bash
~/.openclaw/workspace/skills/us-cpa/scripts/us-cpa --help
```
The wrapper prefers `.venv/bin/python` inside the skill directory when present, so OpenClaw can run the workspace copy without relying on global Python packages.
## Current Milestone
Current implementation now includes:

View File

@@ -10,6 +10,35 @@ From `skills/us-cpa/`:
pip install -e .[dev]
```
## OpenClaw installation
Install the skill into the OpenClaw workspace copy, not only in the repo checkout.
1. Sync the skill into the workspace:
```bash
rsync -a --delete \
/Users/stefano/.openclaw/workspace/projects/stef-openclaw-skills/skills/us-cpa/ \
/Users/stefano/.openclaw/workspace/skills/us-cpa/
```
2. Create a skill-local virtualenv in the workspace copy:
```bash
cd /Users/stefano/.openclaw/workspace/skills/us-cpa
python3 -m venv .venv
. .venv/bin/activate
pip install -e .[dev]
```
3. Run the workspace wrapper:
```bash
~/.openclaw/workspace/skills/us-cpa/scripts/us-cpa --help
```
The wrapper now prefers `~/.openclaw/workspace/skills/us-cpa/.venv/bin/python` when present and falls back to `python3` otherwise.
## Run
Installed entry point:
@@ -24,6 +53,12 @@ Repo-local wrapper without installation:
scripts/us-cpa --help
```
OpenClaw workspace wrapper:
```bash
~/.openclaw/workspace/skills/us-cpa/scripts/us-cpa --help
```
Module execution:
```bash

View File

@@ -40,6 +40,12 @@ skills/us-cpa/scripts/us-cpa review --tax-year 2025 --case-dir ~/tax-cases/2025-
skills/us-cpa/scripts/us-cpa extract-docs --tax-year 2025 --case-dir ~/tax-cases/2025-jane-doe --create-case --case-label "Jane Doe" --facts-json ./facts.json
```
When OpenClaw is using the installed workspace copy, the entrypoint is:
```bash
~/.openclaw/workspace/skills/us-cpa/scripts/us-cpa --help
```
## Rules
- federal individual returns only in v1

View File

@@ -3,6 +3,11 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PYTHON_BIN="${SKILL_DIR}/.venv/bin/python"
export PYTHONPATH="${SKILL_DIR}/src${PYTHONPATH:+:${PYTHONPATH}}"
exec python3 -m us_cpa.cli "$@"
if [[ ! -x "${PYTHON_BIN}" ]]; then
PYTHON_BIN="python3"
fi
exec "${PYTHON_BIN}" -m us_cpa.cli "$@"

View File

@@ -40,6 +40,23 @@ class UsCpaCliSmokeTests(unittest.TestCase):
self.assertIn("scripts/us-cpa", readme)
self.assertIn("python -m unittest", readme)
def test_docs_explain_openclaw_installation_flow(self) -> None:
readme = (SKILL_DIR / "README.md").read_text()
operator_doc = (SKILL_DIR.parent.parent / "docs" / "us-cpa.md").read_text()
skill_doc = (SKILL_DIR / "SKILL.md").read_text()
self.assertIn("OpenClaw installation", readme)
self.assertIn("~/.openclaw/workspace/skills/us-cpa", readme)
self.assertIn(".venv/bin/python", readme)
self.assertIn("OpenClaw installation", operator_doc)
self.assertIn("rsync -a --delete", operator_doc)
self.assertIn("~/.openclaw/workspace/skills/us-cpa/scripts/us-cpa", skill_doc)
def test_wrapper_prefers_local_virtualenv_python(self) -> None:
wrapper = (SKILL_DIR / "scripts" / "us-cpa").read_text()
self.assertIn('.venv/bin/python', wrapper)
self.assertIn('PYTHON_BIN', wrapper)
def test_fixture_directories_exist(self) -> None:
fixtures_dir = SKILL_DIR / "tests" / "fixtures"
for name in ("irs", "facts", "documents", "returns"):