flaude 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. flaude-0.1.0/.env.example +15 -0
  2. flaude-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  3. flaude-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +25 -0
  4. flaude-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  5. flaude-0.1.0/.github/workflows/ci.yml +38 -0
  6. flaude-0.1.0/.github/workflows/docker.yml +49 -0
  7. flaude-0.1.0/.github/workflows/docs.yml +20 -0
  8. flaude-0.1.0/.github/workflows/publish.yml +23 -0
  9. flaude-0.1.0/.gitignore +16 -0
  10. flaude-0.1.0/.pre-commit-config.yaml +17 -0
  11. flaude-0.1.0/AGENTS.md +117 -0
  12. flaude-0.1.0/CHANGELOG.md +23 -0
  13. flaude-0.1.0/CLAUDE.md +46 -0
  14. flaude-0.1.0/CONTRIBUTING.md +61 -0
  15. flaude-0.1.0/LICENSE +21 -0
  16. flaude-0.1.0/PKG-INFO +342 -0
  17. flaude-0.1.0/README.md +282 -0
  18. flaude-0.1.0/SECURITY.md +26 -0
  19. flaude-0.1.0/TODOS.md +26 -0
  20. flaude-0.1.0/docs/api/app-machine.md +21 -0
  21. flaude-0.1.0/docs/api/concurrent.md +11 -0
  22. flaude-0.1.0/docs/api/configuration.md +9 -0
  23. flaude-0.1.0/docs/api/errors.md +7 -0
  24. flaude-0.1.0/docs/api/execution.md +17 -0
  25. flaude-0.1.0/docs/api/image.md +13 -0
  26. flaude-0.1.0/docs/api/log-infrastructure.md +19 -0
  27. flaude-0.1.0/docs/changelog.md +11 -0
  28. flaude-0.1.0/docs/concepts/architecture.md +117 -0
  29. flaude-0.1.0/docs/concepts/log-drain.md +154 -0
  30. flaude-0.1.0/docs/getting-started.md +156 -0
  31. flaude-0.1.0/docs/guide/building-on-flaude.md +214 -0
  32. flaude-0.1.0/docs/guide/concurrent.md +140 -0
  33. flaude-0.1.0/docs/guide/docker-image.md +103 -0
  34. flaude-0.1.0/docs/guide/error-handling.md +145 -0
  35. flaude-0.1.0/docs/guide/private-repos.md +100 -0
  36. flaude-0.1.0/docs/guide/streaming.md +130 -0
  37. flaude-0.1.0/docs/index.md +74 -0
  38. flaude-0.1.0/flaude/.dockerignore +4 -0
  39. flaude-0.1.0/flaude/Dockerfile +45 -0
  40. flaude-0.1.0/flaude/__init__.py +68 -0
  41. flaude-0.1.0/flaude/app.py +132 -0
  42. flaude-0.1.0/flaude/entrypoint.sh +130 -0
  43. flaude-0.1.0/flaude/executor.py +252 -0
  44. flaude-0.1.0/flaude/fly_client.py +147 -0
  45. flaude-0.1.0/flaude/image.py +250 -0
  46. flaude-0.1.0/flaude/lifecycle.py +325 -0
  47. flaude-0.1.0/flaude/log_drain.py +542 -0
  48. flaude-0.1.0/flaude/machine.py +217 -0
  49. flaude-0.1.0/flaude/machine_config.py +165 -0
  50. flaude-0.1.0/flaude/py.typed +0 -0
  51. flaude-0.1.0/flaude/runner.py +368 -0
  52. flaude-0.1.0/mkdocs.yml +85 -0
  53. flaude-0.1.0/pyproject.toml +99 -0
  54. flaude-0.1.0/seed.yaml +83 -0
  55. flaude-0.1.0/tests/__init__.py +0 -0
  56. flaude-0.1.0/tests/conftest.py +54 -0
  57. flaude-0.1.0/tests/test_app.py +235 -0
  58. flaude-0.1.0/tests/test_concurrent_integration.py +667 -0
  59. flaude-0.1.0/tests/test_e2e.py +239 -0
  60. flaude-0.1.0/tests/test_entrypoint.py +381 -0
  61. flaude-0.1.0/tests/test_executor.py +579 -0
  62. flaude-0.1.0/tests/test_exit_code_propagation.py +567 -0
  63. flaude-0.1.0/tests/test_failure_logs.py +352 -0
  64. flaude-0.1.0/tests/test_image.py +234 -0
  65. flaude-0.1.0/tests/test_lifecycle.py +778 -0
  66. flaude-0.1.0/tests/test_log_drain.py +465 -0
  67. flaude-0.1.0/tests/test_log_payload_parsing.py +622 -0
  68. flaude-0.1.0/tests/test_log_stream.py +342 -0
  69. flaude-0.1.0/tests/test_machine.py +365 -0
  70. flaude-0.1.0/tests/test_machine_cleanup_guarantee.py +653 -0
  71. flaude-0.1.0/tests/test_machine_config.py +243 -0
  72. flaude-0.1.0/tests/test_machine_create_config.py +400 -0
  73. flaude-0.1.0/tests/test_prompt_execution.py +348 -0
  74. flaude-0.1.0/tests/test_runner.py +611 -0
  75. flaude-0.1.0/tests/test_startup_env.py +349 -0
  76. flaude-0.1.0/thoughts/plans/2026-03-26-oss-requirements.md +1008 -0
  77. flaude-0.1.0/thoughts/research/2026-03-25-documentation-strategy.md +250 -0
  78. flaude-0.1.0/thoughts/research/2026-03-25-e2e-validation-automation.md +156 -0
  79. flaude-0.1.0/thoughts/research/2026-03-25-oss-requirements.md +212 -0
  80. flaude-0.1.0/uv.lock +1204 -0
@@ -0,0 +1,15 @@
1
+ # Required for E2E tests (flaude/tests/test_e2e.py)
2
+ # Copy to .env: cp .env.example .env
3
+
4
+ # Fly.io API token — https://fly.io/user/personal_access_tokens
5
+ FLY_API_TOKEN=
6
+
7
+ # Claude Code OAuth token for authenticating Claude Code on Fly machines
8
+ CLAUDE_CODE_OAUTH_TOKEN=
9
+
10
+ # GitHub credentials (only needed if cloning private repos)
11
+ GITHUB_USERNAME=
12
+ GITHUB_TOKEN=
13
+
14
+ # Fly.io app name to use for E2E tests
15
+ FLY_APP_NAME=flaude-e2e
@@ -0,0 +1,49 @@
1
+ name: Bug Report
2
+ description: Report a bug in flaude
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for reporting a bug! Please fill out the details below.
9
+
10
+ - type: textarea
11
+ id: description
12
+ attributes:
13
+ label: What happened?
14
+ description: A clear description of the bug.
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: reproduction
20
+ attributes:
21
+ label: Steps to reproduce
22
+ description: Minimal code to reproduce the issue.
23
+ render: python
24
+ validations:
25
+ required: true
26
+
27
+ - type: textarea
28
+ id: expected
29
+ attributes:
30
+ label: Expected behavior
31
+ description: What did you expect to happen?
32
+ validations:
33
+ required: true
34
+
35
+ - type: input
36
+ id: version
37
+ attributes:
38
+ label: flaude version
39
+ placeholder: "e.g. 0.1.0"
40
+ validations:
41
+ required: true
42
+
43
+ - type: input
44
+ id: python
45
+ attributes:
46
+ label: Python version
47
+ placeholder: "e.g. 3.11.8"
48
+ validations:
49
+ required: true
@@ -0,0 +1,25 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or improvement
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: What problem does this solve?
9
+ description: Describe the use case or limitation you're hitting.
10
+ validations:
11
+ required: true
12
+
13
+ - type: textarea
14
+ id: solution
15
+ attributes:
16
+ label: Proposed solution
17
+ description: How would you like this to work?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: alternatives
23
+ attributes:
24
+ label: Alternatives considered
25
+ description: Other approaches you've thought about.
@@ -0,0 +1,18 @@
1
+ ## Summary
2
+
3
+ <!-- What does this PR do? Why? -->
4
+
5
+ ## Changes
6
+
7
+ -
8
+ -
9
+
10
+ ## Testing
11
+
12
+ - [ ] Unit tests pass (`make test`)
13
+ - [ ] Linting passes (`make check`)
14
+ - [ ] Added tests for new behavior (if applicable)
15
+
16
+ ## Related issues
17
+
18
+ Closes #
@@ -0,0 +1,38 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test (Python ${{ matrix.python-version }})
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: astral-sh/setup-uv@v4
19
+ with:
20
+ enable-caching: true
21
+ - name: Install dependencies
22
+ run: uv sync --extra dev
23
+ - name: Run tests with coverage
24
+ run: uv run pytest --cov=flaude --cov-report=xml --cov-fail-under=90
25
+
26
+ lint:
27
+ name: Lint & Type Check
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ - uses: astral-sh/setup-uv@v4
32
+ with:
33
+ enable-caching: true
34
+ - run: uv sync --extra dev
35
+ - run: uv run ruff check .
36
+ - run: uv run ruff format --check .
37
+ - run: uv run mypy flaude/ tests/
38
+ - run: uv run bandit -r flaude/ -ll
@@ -0,0 +1,49 @@
1
+ name: Docker
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ release:
7
+ types: [published]
8
+
9
+ env:
10
+ REGISTRY: ghcr.io
11
+ IMAGE_NAME: ${{ github.repository }}
12
+
13
+ jobs:
14
+ build-and-push:
15
+ name: Build and push Docker image
16
+ runs-on: ubuntu-latest
17
+ permissions:
18
+ contents: read
19
+ packages: write
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Log in to GHCR
25
+ uses: docker/login-action@v3
26
+ with:
27
+ registry: ${{ env.REGISTRY }}
28
+ username: ${{ github.actor }}
29
+ password: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Extract metadata
32
+ id: meta
33
+ uses: docker/metadata-action@v5
34
+ with:
35
+ images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
36
+ tags: |
37
+ type=raw,value=latest,enable={{is_default_branch}}
38
+ type=sha,prefix=sha-
39
+ type=semver,pattern={{version}}
40
+ type=semver,pattern={{major}}.{{minor}}
41
+
42
+ - name: Build and push
43
+ uses: docker/build-push-action@v5
44
+ with:
45
+ context: flaude
46
+ file: flaude/Dockerfile
47
+ push: true
48
+ tags: ${{ steps.meta.outputs.tags }}
49
+ labels: ${{ steps.meta.outputs.labels }}
@@ -0,0 +1,20 @@
1
+ name: Deploy docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ deploy:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.11"
19
+ - run: pip install ".[docs]"
20
+ - run: mkdocs gh-deploy --force
@@ -0,0 +1,23 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write
9
+
10
+ jobs:
11
+ publish:
12
+ name: Build and publish to PyPI
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: astral-sh/setup-uv@v4
18
+
19
+ - name: Build package
20
+ run: uv build
21
+
22
+ - name: Publish to PyPI
23
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,16 @@
1
+ .env
2
+ *.pyc
3
+ .pytest_cache
4
+ .coverage
5
+ .DS_Store
6
+ .ruff_cache
7
+ .mypy_cache
8
+ .venv
9
+ dist
10
+ site/
11
+ __pycache__/
12
+ *.egg-info/
13
+ build/
14
+ htmlcov/
15
+ *.pyo
16
+ .tox/
@@ -0,0 +1,17 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.3.7
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
8
+ - repo: https://github.com/pre-commit/mirrors-mypy
9
+ rev: v1.9.0
10
+ hooks:
11
+ - id: mypy
12
+ args: [--ignore-missing-imports]
13
+ additional_dependencies:
14
+ - pytest
15
+ - pytest-asyncio
16
+ - respx
17
+ - httpx
flaude-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,117 @@
1
+ # AGENTS.md — AI-optimized reference for flaude
2
+
3
+ ## Identity
4
+
5
+ - **Package name**: `flaude`
6
+ - **Purpose**: Python library for executing Claude Code prompts on ephemeral Fly.io machines
7
+ - **Language**: Python 3.11+
8
+ - **Single dependency**: httpx (async HTTP)
9
+ - **No CLI** — library-only, all async
10
+
11
+ ## Architecture
12
+
13
+ ```
14
+ flaude/
15
+ ├── __init__.py # Public API (re-exports everything)
16
+ ├── app.py # Fly.io app CRUD: ensure_app, create_app, get_app
17
+ ├── runner.py # Core execution: run, run_and_destroy, wait_for_machine_exit
18
+ ├── executor.py # Concurrent batch: ConcurrentExecutor, run_batch, run_one
19
+ ├── lifecycle.py # Log-streaming execution: run_with_logs → StreamingRun
20
+ ├── machine.py # Machine CRUD: create_machine, stop_machine, destroy_machine
21
+ ├── machine_config.py # Config dataclasses: MachineConfig, RepoSpec, build_machine_config
22
+ ├── fly_client.py # Low-level HTTP: fly_get, fly_post, fly_delete, fetch_machine_logs, FlyAPIError
23
+ ├── log_drain.py # Log infrastructure: LogDrainServer, LogCollector, LogStream
24
+ ├── image.py # Docker: docker_build, docker_push, ensure_image
25
+ ├── Dockerfile # Container: Node.js 22 + Claude Code + git + gh CLI
26
+ └── entrypoint.sh # Container startup: clone repos → run claude -p → write exit marker
27
+ ```
28
+
29
+ ## Execution modes
30
+
31
+ ### 1. Fire-and-forget (`run_and_destroy`)
32
+ Create machine → wait for exit → destroy. Returns `RunResult`. Raises `MachineExitError` on non-zero exit.
33
+
34
+ ### 2. Streaming (`run_with_logs`)
35
+ Creates `LogDrainServer` before machine → subscribes to logs → returns `StreamingRun` (async iterator + context manager). Background task waits for exit, signals collector, destroys machine.
36
+
37
+ ### 3. Concurrent (`ConcurrentExecutor.run_batch`)
38
+ Dispatches multiple `ExecutionRequest` objects via `asyncio.gather` with optional semaphore. Returns `BatchResult` with per-request `ExecutionResult`.
39
+
40
+ ## Key types
41
+
42
+ ```python
43
+ # Configuration
44
+ MachineConfig(image, claude_code_oauth_token, github_username, github_token, prompt, repos, region, vm_size, vm_cpus, vm_memory_mb, auto_destroy, env, metadata)
45
+ RepoSpec(url, branch="", target_dir="")
46
+
47
+ # Results
48
+ RunResult(machine_id, exit_code, state, destroyed) # frozen dataclass
49
+ MachineExitError(machine_id, exit_code, state, logs) # exception
50
+ BatchResult(results, total, succeeded, failed) # frozen dataclass
51
+ ExecutionResult(tag, run_result, error) # .success property
52
+
53
+ # Execution
54
+ ExecutionRequest(config, name=None, tag="")
55
+ ConcurrentExecutor(app_name, token=None, max_concurrency=None, wait_timeout=3600.0)
56
+ StreamingRun # async iterator + context manager, .result(), .cleanup(), .machine_id
57
+
58
+ # Infrastructure
59
+ FlyApp(name, org, region)
60
+ FlyMachine(id, name, state, region, instance_id, app_name)
61
+ LogDrainServer(collector, host="0.0.0.0", port=0, include_stderr=False)
62
+ LogCollector() # machine_id → asyncio.Queue routing
63
+ LogStream(queue, item_timeout=None, total_timeout=None) # async iterator
64
+ ```
65
+
66
+ ## Critical invariants
67
+
68
+ 1. **Guaranteed cleanup**: Every machine is destroyed in a `try/finally` block — exceptions, cancellations, and timeouts all trigger destruction.
69
+ 2. **Log drain before machine**: `LogDrainServer` starts before `create_machine` so no early log lines are lost.
70
+ 3. **Exit code fallback**: If Fly API doesn't report exit code, `entrypoint.sh` writes `[flaude:exit:N]` marker parsed by `extract_exit_code_from_logs`.
71
+ 4. **Never raises in batch**: `ConcurrentExecutor._execute_one` catches all exceptions into `ExecutionResult.error`.
72
+ 5. **Restart policy is "no"**: Machines run once and stop. `auto_destroy=True` by default.
73
+
74
+ ## Container image
75
+
76
+ - **Base**: `node:22-bookworm-slim`
77
+ - **Pre-installed**: git, jq, gh (GitHub CLI), `@anthropic-ai/claude-code` (npm global)
78
+ - **Entrypoint flow**: validate `CLAUDE_CODE_OAUTH_TOKEN` → configure git credentials → clone repos from `FLAUDE_REPOS` JSON → `cd` to workspace → `claude -p -- "$FLAUDE_PROMPT"` → write exit marker → exit
79
+
80
+ ## Environment variables
81
+
82
+ **Host-side** (your process):
83
+ - `FLY_API_TOKEN` — Fly.io API authentication
84
+
85
+ **Machine-side** (set automatically by `build_machine_config`):
86
+ - `CLAUDE_CODE_OAUTH_TOKEN` — Claude Code auth
87
+ - `FLAUDE_PROMPT` — The prompt string
88
+ - `FLAUDE_REPOS` — JSON array of `{url, branch?, target_dir?}`
89
+ - `GITHUB_USERNAME` / `GITHUB_TOKEN` — Git credentials (optional)
90
+
91
+ ## Fly.io API interaction
92
+
93
+ All API calls go through `fly_client.py` which wraps httpx:
94
+ - **Machines API**: `https://api.machines.dev/v1` — auth via `Bearer {FLY_API_TOKEN}`
95
+ - **Platform API**: `https://api.fly.io` — auth via raw token as `Authorization` header (no `Bearer` prefix)
96
+ - Machine wait: `GET /apps/{app}/machines/{id}/wait?state=stopped` (long-poll), with polling fallback
97
+ - Log retrieval: `GET https://api.fly.io/api/v1/apps/{app}/logs?instance={machine_id}` — historical logs (~15 day retention), works after machine exit/destroy
98
+ - Terminal states: `stopped`, `destroyed`, `failed`
99
+ - Exit code extraction: `event["request"]["exit_event"]["exit_code"]` (or via `monitor_event` wrapper)
100
+
101
+ ## Testing
102
+
103
+ - **Framework**: pytest + pytest-asyncio (auto mode)
104
+ - **HTTP mocking**: respx
105
+ - **18 test files** covering: app, machine, config, runner, executor, lifecycle, log drain, log stream, log parsing, entrypoint, exit codes, cleanup guarantees, concurrent integration, failure logs, image, startup env, prompt execution
106
+ - **Run unit tests**: `pytest` (E2E excluded by default via `addopts = "-m 'not e2e'"`)
107
+ - **Run E2E tests**: `source .env && pytest -m e2e -v`
108
+ - **E2E requires**: `FLY_API_TOKEN` + `CLAUDE_CODE_OAUTH_TOKEN` (both in `.env`) + Docker image pushed
109
+ - **E2E test files**: `tests/conftest.py` (fixtures), `tests/test_e2e.py` (5 tests)
110
+ - **E2E validates**: machine lifecycle, log retrieval via platform API, public/private repo clone, cleanup guarantee
111
+ - **Docker image**: Built with `--platform linux/amd64` (required by Fly.io, even on ARM hosts)
112
+
113
+ ## Default machine spec
114
+
115
+ - VM size: `performance-2x` (2 shared CPUs, 4 GB RAM)
116
+ - Region: `iad` (US East)
117
+ - Image: `registry.fly.io/flaude:latest`
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to flaude will be documented here.
4
+
5
+ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ Versions follow [Semantic Versioning](https://semver.org/).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-03-25
11
+
12
+ ### Added
13
+ - Initial release
14
+ - `MachineConfig` for configuring Fly.io machine execution parameters
15
+ - `run_and_destroy()` for fire-and-forget prompt execution
16
+ - `run_with_logs()` for streaming log output
17
+ - `ensure_app()` for idempotent Fly.io app creation
18
+ - Automatic machine cleanup via `try/finally` guarantee
19
+ - Support for cloning multiple repos into `/workspace`
20
+ - Concurrent execution support
21
+
22
+ [Unreleased]: https://github.com/ravi-hq/flaude/compare/v0.1.0...HEAD
23
+ [0.1.0]: https://github.com/ravi-hq/flaude/releases/tag/v0.1.0
flaude-0.1.0/CLAUDE.md ADDED
@@ -0,0 +1,46 @@
1
+ <!-- ooo:START -->
2
+ <!-- ooo:VERSION:0.14.0 -->
3
+ # Ouroboros — Specification-First AI Development
4
+
5
+ > Before telling AI what to build, define what should be built.
6
+ > As Socrates asked 2,500 years ago — "What do you truly know?"
7
+ > Ouroboros turns that question into an evolutionary AI workflow engine.
8
+
9
+ Most AI coding fails at the input, not the output. Ouroboros fixes this by
10
+ **exposing hidden assumptions before any code is written**.
11
+
12
+ 1. **Socratic Clarity** — Question until ambiguity ≤ 0.2
13
+ 2. **Ontological Precision** — Solve the root problem, not symptoms
14
+ 3. **Evolutionary Loops** — Each evaluation cycle feeds back into better specs
15
+
16
+ ```
17
+ Interview → Seed → Execute → Evaluate
18
+ ↑ ↓
19
+ └─── Evolutionary Loop ─────┘
20
+ ```
21
+
22
+ ## ooo Commands
23
+
24
+ Each command loads its agent/MCP on-demand. Details in each skill file.
25
+
26
+ | Command | Loads |
27
+ |---------|-------|
28
+ | `ooo` | — |
29
+ | `ooo interview` | `ouroboros:socratic-interviewer` |
30
+ | `ooo seed` | `ouroboros:seed-architect` |
31
+ | `ooo run` | MCP required |
32
+ | `ooo evolve` | MCP: `evolve_step` |
33
+ | `ooo evaluate` | `ouroboros:evaluator` |
34
+ | `ooo unstuck` | `ouroboros:{persona}` |
35
+ | `ooo status` | MCP: `session_status` |
36
+ | `ooo setup` | — |
37
+ | `ooo help` | — |
38
+
39
+ ## Agents
40
+
41
+ Loaded on-demand — not preloaded.
42
+
43
+ **Core**: socratic-interviewer, ontologist, seed-architect, evaluator,
44
+ wonder, reflect, advocate, contrarian, judge
45
+ **Support**: hacker, simplifier, researcher, architect
46
+ <!-- ooo:END -->
@@ -0,0 +1,61 @@
1
+ # Contributing to flaude
2
+
3
+ Thank you for your interest in contributing!
4
+
5
+ ## Development setup
6
+
7
+ **Prerequisites**: Python 3.11+, [uv](https://docs.astral.sh/uv/), a Fly.io account (for E2E tests only).
8
+
9
+ ```bash
10
+ git clone https://github.com/ravi-hq/flaude.git
11
+ cd flaude
12
+ uv sync --extra dev
13
+ ```
14
+
15
+ ## Running tests
16
+
17
+ ```bash
18
+ # Unit tests (no external dependencies)
19
+ uv run pytest
20
+
21
+ # With coverage
22
+ uv run pytest --cov=flaude
23
+
24
+ # E2E tests (requires FLY_API_TOKEN and CLAUDE_CODE_OAUTH_TOKEN in .env)
25
+ cp .env.example .env # fill in your credentials
26
+ uv run pytest -m e2e
27
+ ```
28
+
29
+ ## Linting and type checking
30
+
31
+ ```bash
32
+ uv run ruff check .
33
+ uv run ruff format --check .
34
+ uv run mypy flaude
35
+ ```
36
+
37
+ ## Submitting a pull request
38
+
39
+ 1. Fork the repo and create a branch from `main`.
40
+ 2. Make your changes with tests for any new behaviour.
41
+ 3. Run the linter and tests locally — CI must pass.
42
+ 4. Open a PR against `main` with a clear description of what and why.
43
+ 5. A maintainer will review and merge.
44
+
45
+ ## Reporting bugs
46
+
47
+ Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.yml).
48
+
49
+ ## Requesting features
50
+
51
+ Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.yml).
52
+
53
+ ## Code style
54
+
55
+ - Black-compatible formatting enforced by `ruff format`.
56
+ - Type annotations required on all public functions.
57
+ - Async-first: use `httpx.AsyncClient` and `asyncio`; avoid blocking calls.
58
+
59
+ ## License
60
+
61
+ By contributing you agree that your contributions will be licensed under the [MIT License](LICENSE).
flaude-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 flaude contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.