> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pensar.dev/apex/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pensar.dev/apex/_mcp/server.

# sessions

> Create, load, and delete the sessions that hold Apex agent configuration and artifacts

A session is a directory under `~/.pensar/sessions/<id>/`, together with the configuration for one engagement: targets, scope, credentials, headers, and safety switches. Every agent runner takes a `session`, writes its findings, POCs, and logs into it, and reads its configuration from it.

**`Import`**

```ts title="Import"
import { sessions } from "@pensar/apex/core/session";
```

**`Session directory`**

```text title="Session directory"
~/.pensar/sessions/<id>/
├── session.json   # SessionInfo, including config
├── README.md
├── findings/      # One file per documented vulnerability
├── pocs/          # Proof-of-concept scripts
├── logs/          # Execution logs
└── scratchpad/    # Agent notes
```

## sessions.create

**`Signature`**

```ts title="Signature"
function create(input: CreateInputProps): Promise<SessionInfo>;
```

Creates the session directory and returns the session.

**`targets`** `string[]` — required

URLs, hosts, or IPs in scope. Unless `config.scopeConstraints.allowedHosts` is set, these hostnames define the in-scope hosts.

---

**`name`** `string`

Display name. When omitted, a random name is used, or an AI-generated one if `model` and `authConfig` are provided.

---

**`config`** `SessionConfig`

Configuration for agents that run in this session. See [Session config](#session-config).

---

**`prefix`** `string`

Prefix for the session ID, for example `"ci-"`.

---

**`model`** `AIModel`

Model used to generate a session name in the background. Only used when `name` is omitted.

---

**`authConfig`** `AIAuthConfig`

Credentials for name generation.

---

### Returns: `SessionInfo`

**`id`** `string`

Unique session ID.

---

**`rootPath`** `string`

Absolute path to the session directory.

---

**`findingsPath`** `string`

Absolute path to `findings/`.

---

**`pocsPath`** `string`

Absolute path to `pocs/`.

---

**`logsPath`** `string`

Absolute path to `logs/`.

---

**`targets`** `string[]`

The session's targets.

---

**`config`** `SessionConfig`

The resolved configuration, including defaults such as `headers` and `outcomeGuidance`.

---

## Session config

All fields are optional.

### Scope and safety

**`scopeConstraints`** `{ allowedHosts?: string[]; allowedPorts?: number[]; strictScope?: boolean }`

`allowedHosts` overrides the in-scope hosts derived from `targets`. It supports wildcards such as `*.example.com`. With `strictScope: true`, requests to out-of-scope hosts or ports fail, even after redirects or newly discovered assets.

---

**`requestsPerSecond`** `number`

Rate limit for outbound requests to the target.

---

**`allowDestructiveActions`** `boolean` — default: false

Allow destructive testing: financial mutations, database deletes and drops, and destructive API writes. When `false`, those operations are blocked at the tool layer.

---

**`allowRateLimitTesting`** `boolean` — default: false

Allow burst and volumetric testing to probe for missing rate limits. Endpoints with real-world side effects, such as email, SMS, and payments, are never looped either way.

---

**`enumerateSubdomains`** `boolean` — default: false

Enumerate subdomains during attack surface discovery.

---

**`exfilMode`** `boolean` — default: false

CTF-style mode: allows pivoting and flag extraction through confirmed vulnerabilities.

---

**`outcomeGuidance`** `string`

What counts as a successful exploit. Defaults to proving exploitability without exfiltrating data or causing harm.

---

### Authentication credentials

**`authCredentials`** `AuthCredentials | AuthCredentials[]`

Credentials agents can log in with. Agents see only credential references in their prompts; tools resolve the secrets at execution time. Pass an array to test with multiple roles.

---

**`username`** `string`

Login username or email.

---

**`password`** `string`

Login password.

---

**`loginUrl`** `string`

Login page URL.

---

**`apiKey`** `string`

API key, for API-key auth.

---

**`role`** `string`

Role label, such as `admin` or `viewer`, used for authorization testing.

---

**`tokens`** `{ bearerToken?: string; cookies?: string; sessionToken?: string; customHeaders?: Record<string, string> }`

Existing tokens to reuse instead of logging in.

---

**`googleSignIn`** `boolean`

The target uses Sign in with Google.

---

> **Warning**
>
> `authCredentials` is saved as part of the session config in `session.json`, in plaintext. Treat `~/.pensar/sessions/` as sensitive, and delete sessions with `sessions.remove()` when you no longer need them.

**`authenticationInstructions`** `string`

Free-form instructions for the login flow.

---

### Requests

**`headers`** `Record<string, string>`

Headers sent on every in-scope request (HTTP tools, supported CLI tools, and browser navigation). When omitted, the global `pensar config headers` defaults are copied in at creation time. Pass `{}` to send no custom headers.

---

### Agent behavior

**`codebasePath`** `string`

Source code path for whitebox analysis.

---

**`prompt`** `string`

Operator guidance injected into agent system prompts.

---

**`disableSubagents`** `boolean` — default: false

Run targeted pentests as one worker instead of one sub-agent per objective. Cheaper and faster, but less thorough.

---

**`requirePlan`** `boolean` — default: false

Run a planning phase before pentest agents start executing.

---

**`taskDriven`** `boolean` — default: false

Experimental. Agents break objectives down into tracked tasks.

---

## sessions.get

**`Signature`**

```ts title="Signature"
function get(id: string): Promise<SessionInfo>;
```

Loads a session from disk. A loaded session's `config.authCredentials` is present, but its credential manager isn't rebuilt. To run authenticated agents again, create a new session with the credentials.

## sessions.remove

**`Signature`**

```ts title="Signature"
function remove(input: { sessionId: string }): Promise<void>;
```

Deletes the session directory and everything in it.

## list

**`Signature`**

```ts title="Signature"
function list(): AsyncGenerator<SessionInfo>;
```

Yields every session in `~/.pensar/sessions/`. Directories without a valid `session.json` are skipped.

```ts
import { list } from "@pensar/apex/core/session";

for await (const s of list()) {
  console.log(s.id, s.name, s.targets.join(", "));
}
```

## Example

**`A scoped, authenticated session`**

```ts title="A scoped, authenticated session"
const session = await sessions.create({
  name: "Staging — nightly",
  prefix: "ci-",
  targets: ["https://staging.example.com"],
  config: {
    scopeConstraints: {
      allowedHosts: ["staging.example.com", "*.staging-api.example.com"],
      strictScope: true,
    },
    requestsPerSecond: 5,
    headers: { "X-Pentest-Run": process.env.CI_RUN_ID ?? "local" },
    authCredentials: [
      { username: "admin@example.com", password: process.env.ADMIN_PW, role: "admin" },
      { username: "viewer@example.com", password: process.env.VIEWER_PW, role: "viewer" },
    ],
  },
});
```