where-are-we
The first question in an unfamiliar repository — answered in seconds, without a model.
Any codebase · any language · any agent
pip install where-are-we
where-are-we --repo . --agent-file AGENTS.md
That is the whole setup. The next agent session opens already knowing where it is.
Who this is for
You run agents on a codebase. Every session opens with the same forty tool calls: where do the tests live, what may a step call, how is a scenario launched, which environment variables must be set, what does the product expose. At a minute a turn that is half an hour of your budget, per session, for answers that never change between sessions and need no model to produce.
You maintain a pipeline that fans out. Seven branches means seven copies of that half hour, in parallel, every run. This was built when three runs in a row died at their deadline with the branches still reading.
Someone new is joining. The same map is the onboarding document, and it cannot go stale: it is rebuilt from the checkout, not written by hand.
You inherited a repository nobody can explain. Point it at the thing and read what comes out — routes, data model, queues, schedules, dead code, who has been touching what.
What you get
| file | what it is | typical size |
|---|---|---|
framework_map_brief.md |
the digest to put in a prompt | 40–85 KB, sizeable with --only / --max-lines |
framework_map.md |
the full map: every step phrase, every scenario with its line number | ~135 KB |
framework_map.json |
the same as data — versioned contract, see SCHEMA.md | — |
--agent-file writes the brief between markers into AGENTS.md, CLAUDE.md,
.cursorrules, .github/copilot-instructions.md — anything else in the file
survives.
What it reads
Supported
Test runners — behave · pytest · jest · vitest · playwright · cypress · robot · JUnit · TestNG · Cucumber-JVM (Java, Kotlin, Scala) · cucumber-js (TypeScript, JavaScript) · cucumber-ruby · rspec · go test · xUnit · NUnit · SpecFlow · PHPUnit · Behat · Rust · XCTest · karate · gauge · k6 · gatling
Languages — Python · TypeScript · JavaScript · Go · Java · Kotlin · Scala · Ruby · Rust · C# · PHP · Swift · C/C++ · Shell · SQL · Protobuf · Elixir · Erlang · Dart · Groovy · Clojure · Haskell · Lua · Perl · R · Julia · Objective-C · F# · VB.NET · Solidity
More test runners — ExUnit · Flutter · Spock · clojure.test · hspec · busted · Perl Test · Foundry · Julia · Espresso · XCUITest · Detox
Frontend — React · Vue · Svelte · Angular · Storybook
Data — dbt · Airflow · Spark · notebooks
Contracts — OpenAPI · GraphQL · AsyncAPI · JSON Schema · Avro · Thrift · SOAP/WSDL · tRPC · Pact
Web frameworks — Flask · FastAPI · Django · Express · Nest · Go net/http and chi · Spring · Rails
Infrastructure — Docker · Compose · Kubernetes · Helm · Terraform · CloudFormation · Pulumi · Bicep · Ansible · Chef · Puppet
CI — GitHub Actions · GitLab CI · Jenkins · CircleCI · Azure Pipelines · Travis · Buildkite · Drone · Bitbucket
Build — Make · Gradle · Maven · Bazel · sbt · CMake · Rake · npm/pnpm workspaces
Datastores and brokers — PostgreSQL and friends · MongoDB · Elasticsearch · DynamoDB · Cassandra · ClickHouse · Kafka · RabbitMQ · SQS · NATS · Pulsar · MQTT
Observability and policy — Prometheus rules · Grafana dashboards · OpenTelemetry · OPA/Rego · LaunchDarkly · Unleash
Load testing — JMeter · Locust · Artillery · k6 · gatling
Detection is by shape, not by directory name: a page object is a class that owns selectors — wherever it lives, whatever the team calls it. Point it at a repository before you know what is in it.
When the repository knows better
Autodetection gets the shape right and the vocabulary wrong. A repository states its own, and what it states wins:
where-are-we --repo . --init # a starter manifest, from what was detected
{
"name": "billing-e2e",
"purpose": "End-to-end tests for the billing portal.",
"layers": {"steps": "steps/*.py — steps own no selectors, they call page objects"},
"product_src": ["../billing-web/src"],
"conventions": ["After a fix, re-run only what failed."]
}
.framework-map.json at the root, or the same block fenced as
```framework-map in README.md.
Directories can explain themselves too:
wawe-readmes --repo . # a README in every content directory that lacks one,
# derived from what is in it, one TODO line for a human
The map reads them back.
Keeping it current
The commit and the newest file in the tree are recorded with the map, so running it on every checkout costs a stat walk and nothing else.
where-are-we --repo . --install-hook git # post-checkout, post-merge, post-commit
where-are-we --repo . --install-hook agent # SessionStart, before the first turn
where-are-we --repo . --diff # what changed since the last map
Options
--repo PATH the repository to index
--product PATH,… source roots of the application under test
--out DIR where the three files land
--agent-file FILE also write the brief into AGENTS.md / CLAUDE.md / …
--only "routes,data model" keep only these sections in the brief
--skip "coverage,history" drop these
--max-lines N cap the brief; the full map is untouched
--diff what changed since the map already in --out
--init write a starter .framework-map.json
--install-hook git|agent wire it into something that already runs
--rules PATH a corpus of rules to list by name
--runs-api URL a runs database, to carry what earlier runs concluded
--force rebuild even when nothing moved
--quiet no summary line
.wawe-ignore (falling back to .gitignore) keeps build output out;
WAWE_MAX_FILES bounds the walk.
As a library
from where_are_we import build, brief
m = build("/path/to/repo")
print(m["counts"], len(m["routes_served"]))
open("AGENTS.md", "w").write(brief(m))
Why it exists
It was built inside an agentic QA pipeline where seven branches ran at once and
each opened the same way: forty greps to find where the steps live, which page
object owns the portal, how the driver is built, what environment.py does.
Identical in every branch, identical every run, derivable without a model — and
three runs died at their deadline with the branches still reading.
Nothing about it turned out to be specific to that pipeline, that agent, or that language.
Contributing
Issues and pull requests welcome — see CONTRIBUTING.md.
Changes are expected to keep the JSON contract in SCHEMA.md and to
come with a case in tests/ built from a real directory.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file where_are_we-0.2.0.tar.gz.
File metadata
- Download URL: where_are_we-0.2.0.tar.gz
- Upload date:
- Size: 52.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb2d271283308d70da500ae9e977f3f25420a5b77272f9ff68506773649df160
|
|
| MD5 |
719742773beeb0910310e92ee51214eb
|
|
| BLAKE2b-256 |
d5b1e1d7ff6e7dba379906bacf13435aa5fcdcd4360cef107ea88ca10a0014e4
|
File details
Details for the file where_are_we-0.2.0-py3-none-any.whl.
File metadata
- Download URL: where_are_we-0.2.0-py3-none-any.whl
- Upload date:
- Size: 48.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6c255452c9ffcef14f97fedc9e5a0a3f60457f5dd7656d954605ce93a492e7b
|
|
| MD5 |
07f33a92c8aefdbbe05c18f20847ad23
|
|
| BLAKE2b-256 |
a7fd26b56564b7aea340d2114be6e41283083f9c2466c8f84a241ce80b04cfa4
|