# Init Spec
This spec covers the creation of a spens init command, which sets up a local spens.config.json file and updates the .gitignore.

## Spens Init
When a user types 

```bash 
spens init
```
They should be prompted with a setup questionnaire that asks 

1. What type of stack is used (Node, Python, .Net, Rust, Go, Java, manual)
2. Do they want to allow public get access for the internet? (y/n)
3. Do they want to allow access to common urls for tooling? (y/n)
4. What model provider are they using? (fireworks, anthropic, openrouter, openai, manual)
5. Do they want to configure common env variables for the provider? (y/n)

Upon completion it should generate a valid spens.config.json file that matches their answers. 

## How it works 
There are a set of config template files in data that represent partial configurations for the answers. 

### Stack Used
Each stack option has a file in data/init_templates that defines common domain_rules needed for tooling. 

If the user answers yes to question 3, those urls and their methods are added to the generated spens configuration. 

If a user answers manual to question 1 nothing will be configured and question 3 will be omitted from the flow.
#### Stack URLs
Node.js (npm/yarn/pnpm/bun)	
registry.npmjs.org, npm.pkg.github.com, nodejs.org, yarnpkg.com, bun.sh, GitHub CDN domains	
GET, HEAD, POST, PUT

Python (pip/Poetry/uv/Conda)	
pypi.org, files.pythonhosted.org, repo.anaconda.com, astral.sh, GitHub CDN domains	
GET, HEAD, POST

.NET (NuGet/dotnet)	
api.nuget.org, packages.nuget.org, dist.nuget.org, Azure DevOps feeds, dotnet SDK CDNs, DigiCert CRL/OCSP	
GET, HEAD, POST, PUT

Rust (Cargo/crates.io/rustup)	
crates.io, index.crates.io, static.crates.io, static.rust-lang.org, sh.rustup.rs	
GET, HEAD, POST, PUT

Go (modules/GOPROXY)	
proxy.golang.org, sum.golang.org, index.golang.org, dl.google.com, go.googlesource.com, GitHub/GitLab/Bitbucket	
GET, HEAD

Java (Maven/Gradle)	
repo1.maven.org, plugins.gradle.org, services.gradle.org, oss.sonatype.org, jitpack.io	
GET, HEAD, POST, PUT

### Public Access
If the user answers yes to this a * with ["get"] rule is written to the configuration. 

### What model provider
The model provider question works like the stack used where in data/init_templates there are files for each provider. Those files provide configuration information around domain_rules, addition_capture_urls and exclude_capture_urls. It also contains common env vars which if the user answers yes to 5 will get added to the configuration. 

A user can select multiple providers, in which case the data will be merged from configurations.

After the user answers 4 the domain_rules, addition_capture_urls and exclude_capture_urls will be populated. If the user answers yes to 5 the env and inject_headers will be configured. 

If a user answers manual nothing will be configured.

#### Provider URLs
Fireworks AI	api.fireworks.ai	POST /inference/v1/chat/completions	Bearer token
Anthropic	api.anthropic.com	POST /v1/messages	x-api-key + anthropic-version header
OpenRouter	openrouter.ai	POST /api/v1/chat/completions	Bearer token
OpenAI	api.openai.com	POST /v1/chat/completions or POST /v1/responses	Bearer token

#### Provider Env vars

Each provider template defines two categories of env vars:

- **Inject vars**: Secrets and tokens that should be injected as HTTP headers by the proxy (e.g., API keys, auth tokens). These populate the `inject_headers` array in the config.
- **Forward vars**: Non-secret configuration values that should be forwarded from the host into the agent container (e.g., base URLs, model names, organization IDs). These populate the `env` array in the config.

OpenAI	
  Inject: OPENAI_API_KEY	
  Forward: OPENAI_BASE_URL, OPENAI_ORGANIZATION, OPENAI_PROJECT	
  Auth: Bearer token

Anthropic	
  Inject: ANTHROPIC_API_KEY or ANTHROPIC_AUTH_TOKEN	
  Forward: ANTHROPIC_BASE_URL, ANTHROPIC_MODEL, ANTHROPIC_VERSION	
  Auth: x-api-key or Bearer

Fireworks AI	
  Inject: FIREWORKS_API_KEY	
  Forward: FIREWORKS_BASE_URL, FIREWORKS_ACCOUNT_ID	
  Auth: Bearer token

OpenRouter	
  Inject: OPENROUTER_API_KEY	
  Forward: OPENROUTER_API_BASE, OR_SITE_URL, OR_APP_NAME	
  Auth: Bearer token

## Coding standards
Please create the initiation logic in a separate file (following the style for builder, runner, viewer etc) that is invoked through the CLI. Ensure everything is templated for ease of later management. Ensure unit tests are created to validate generation behavior.

### .gitignore updates
The init should also read the .gitignore and add .spens to the ignore.

### Existing config
When init runs it should check for a configuration, if one exists present a warning that it will overwrite the configuration and ask if they wish to proceed.

### Non Interactive mode
In non interactive mode a user can provide answers to the command to answer questions. If a user provides no answer it assumes the default. Stack and Provider are required when using `--yes`; if either is missing the command will error.

Question 3 and 5 = Yes
Question 2 = No

```bash
spens init [OPTIONS]

NON-INTERACTIVE:
  --yes, -y                      Skip all prompts; use defaults for unspecified answers.
                                  Requires --stack and --provider to be specified.

QUESTION OVERRIDES (map 1:1 to the questionnaire):
  --stack <stack>                node | python | dotnet | rust | go | java | manual
  --provider <provider(s)>       fireworks | anthropic | openrouter | openai | manual
                                 (comma-separated for multiple: openai,fireworks)
  --public-get / --no-public-get        Allow/deny public GET access (default: deny)
  --tooling-urls / --no-tooling-urls    Allow/deny stack tooling URLs (default: allow)
  --inject-env / --no-inject-env        Configure provider env vars: inject secrets as
                                        headers and forward non-secret vars (default: allow)
OUTPUT:
  --output <path>                Config file path (default: .spens.config.json)
  --force                        Overwrite existing config without prompting
  --dry-run                      Print generated config to stdout, don't write file
```

## Example configuration
```json
{
  "addition_capture_urls": ["*opencode.ai*", "*api.fireworks.ai*", "*192.168.8.10*"],
  "exclude_capture_urls": ["*models.opencode.ai*"],
  "env": ["ANTHROPIC_BASE_URL", "ANTHROPIC_MODEL", "ANTHROPIC_VERSION"],
  "domain_rules": [
    {"pattern": "*github.com", "allow": ["GET"]},
    {"pattern": "*release-assets.githubusercontent.com", "allow": ["GET"]},
    {"pattern": "*pi.dev", "allow": ["GET"]},
    {"pattern": "*npmjs.org", "allow": ["GET"]},
    {"pattern": "*pypi.org", "allow": ["GET"]},
    {"pattern": "*files.pythonhosted.org", "allow": ["GET"]},
    {"pattern": "*platform.claude.com", "allow": ["GET"]},
    {"pattern": "*api.anthropic.com", "allow": ["GET", "POST", "PUT", "DELETE", "OPTIONS"]},
    {"pattern": "*opencode.ai", "allow": ["GET", "POST", "PUT", "DELETE", "OPTIONS"]},
    {"pattern": "*api.fireworks.ai", "allow": ["GET", "POST", "PUT", "DELETE", "OPTIONS"]}
  ],
  "inject_headers": [
    {
      "placeholder": "ANTHROPIC_API_KEY",
      "env_var": "ANTHROPIC_API_KEY",
      "for_domains": ["*api.anthropic.com*"]
    }
  ]
}
```
