> ## Documentation Index
> Fetch the complete documentation index at: https://docs.airstore.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Source Views

> Materialized queries over your connected data sources

A source view is a query against a connected integration — GitHub, Gmail, Slack, etc. — whose results are materialized as files in the virtual filesystem. You create a view, Airstore executes the query, and the matching data appears as a folder you can mount and read.

There are two ways to define a view:

* **Smart mode** — describe what you want in natural language and an LLM translates it into the appropriate API query.
* **Query mode** — provide a structured filter object with explicit fields. No LLM involved; you get deterministic, repeatable results.

<Note>
  In smart mode, results are interpreted by an LLM, not exact matches. Be specific in your guidance for best results. Query mode gives you full control when you need precision.
</Note>

## Smart mode

Smart mode is the fastest way to get started. Provide a name and a `guidance` string describing what you want:

```
Name: "Design Issues"
Guidance: "all Linear issues related to design or frontend UX"
```

Airstore sends your guidance to an LLM, which translates it into the source's native query format (Gmail search syntax, GitHub search qualifiers, etc.), executes the query, and materializes the results as files.

### Good guidance examples

| Source  | Guidance                                       | What you get                   |
| ------- | ---------------------------------------------- | ------------------------------ |
| Gmail   | `"emails from investors in the last 30 days"`  | Recent investor correspondence |
| GitHub  | `"open PRs in acme/api with full diffs"`       | PR diffs ready for review      |
| Linear  | `"high priority issues in the current sprint"` | Urgent work items              |
| Drive   | `"PDF contracts from 2024"`                    | Last year's contracts          |
| Notion  | `"meeting notes from January"`                 | Recent meeting docs            |
| Slack   | `"messages in #engineering about deployments"` | Relevant channel history       |
| PostHog | `"active feature flags"`                       | Currently enabled flags        |

## Query mode

Query mode lets you define views with structured filters — specific fields per integration, no LLM interpretation. This is useful when you know exactly what you want, or when you're building automation that needs deterministic results.

In the dashboard, toggle the mode selector from **Smart** to **Query**, then fill in the filter fields for your integration.

Via the SDK:

```typescript theme={null}
await airstore.views.create('ws_abc123', {
  integration: 'github',
  name: 'Open PRs',
  filter: {
    repo: 'acme/api',
    type: 'prs',
    state: 'open',
    content_type: 'diff',
  },
})
```

When you provide a `filter` object instead of `guidance`, the view is automatically created in query mode.

## Per-integration filters

Each integration supports a different set of filter fields. All fields are optional unless noted otherwise.

### GitHub

| Field          | Type     | Description                                                                             |
| -------------- | -------- | --------------------------------------------------------------------------------------- |
| `repo`         | `string` | **Required.** Repository in `owner/repo` format                                         |
| `type`         | `string` | Resource type: `issues`, `prs`, `commits`, `files`, `releases`, `workflows`, `branches` |
| `state`        | `string` | `open`, `closed`, or `merged`                                                           |
| `label`        | `string` | Filter by label name                                                                    |
| `author`       | `string` | Filter by author username                                                               |
| `content_type` | `string` | Output format: `markdown`, `diff`, `json`, `raw` (see [Content types](#content-types))  |

### Gmail

| Field            | Type      | Description                                                                     |
| ---------------- | --------- | ------------------------------------------------------------------------------- |
| `from`           | `string`  | Sender email address                                                            |
| `to`             | `string`  | Recipient email address                                                         |
| `subject`        | `string`  | Subject line keyword                                                            |
| `label`          | `string`  | Gmail label: `inbox`, `sent`, `starred`, `important`, `drafts`, `spam`, `trash` |
| `newer_than`     | `string`  | Relative date, e.g. `"7d"`, `"2w"`, `"1m"`                                      |
| `older_than`     | `string`  | Relative date, e.g. `"30d"`                                                     |
| `has_attachment` | `boolean` | Only emails with attachments                                                    |
| `is_unread`      | `boolean` | Only unread emails                                                              |
| `is_starred`     | `boolean` | Only starred emails                                                             |

### Slack

| Field          | Type      | Description                          |
| -------------- | --------- | ------------------------------------ |
| `channel`      | `string`  | Channel name (e.g. `"general"`)      |
| `from`         | `string`  | Username of the message sender       |
| `after`        | `string`  | Messages after this date (ISO 8601)  |
| `before`       | `string`  | Messages before this date (ISO 8601) |
| `has_link`     | `boolean` | Only messages containing links       |
| `has_reaction` | `boolean` | Only messages with reactions         |

### Linear

| Field      | Type     | Description                                          |
| ---------- | -------- | ---------------------------------------------------- |
| `type`     | `string` | `issues` or `projects`                               |
| `team`     | `string` | Team identifier                                      |
| `state`    | `string` | `backlog`, `todo`, `in_progress`, `done`, `canceled` |
| `assignee` | `string` | Assignee username                                    |
| `priority` | `string` | `urgent`, `high`, `medium`, `low`                    |
| `label`    | `string` | Label name                                           |

### Google Drive

| Field             | Type      | Description                                               |
| ----------------- | --------- | --------------------------------------------------------- |
| `name_contains`   | `string`  | File name search                                          |
| `mime_type`       | `string`  | `pdf`, `document`, `spreadsheet`, `presentation`, `image` |
| `shared_with_me`  | `boolean` | Only shared files                                         |
| `starred`         | `boolean` | Only starred files                                        |
| `modified_after`  | `string`  | Modified after this date (ISO 8601)                       |
| `modified_before` | `string`  | Modified before this date (ISO 8601)                      |
| `folder_id`       | `string`  | Restrict to a specific folder                             |

### Notion

| Field    | Type     | Description                                 |
| -------- | -------- | ------------------------------------------- |
| `search` | `string` | Full-text search across pages and databases |

### PostHog

| Field        | Type     | Description                                      |
| ------------ | -------- | ------------------------------------------------ |
| `type`       | `string` | `events`, `feature-flags`, `insights`, `cohorts` |
| `query`      | `string` | Search keyword                                   |
| `project_id` | `number` | PostHog project ID                               |

### Web

| Field           | Type       | Description                  |
| --------------- | ---------- | ---------------------------- |
| `mode`          | `string`   | `map` or `search`            |
| `url`           | `string`   | Starting URL                 |
| `query`         | `string`   | Search query                 |
| `include_paths` | `string[]` | URL path prefixes to include |

## Content types

GitHub views support a `content_type` field that controls the output format of each file:

| Content type | Description                                  | File extension |
| ------------ | -------------------------------------------- | -------------- |
| `json`       | Structured JSON with full metadata (default) | `.json`        |
| `markdown`   | Human-readable markdown rendering            | `.md`          |
| `diff`       | Unified diff format (PRs and commits)        | `.md`          |
| `raw`        | Raw content from the GitHub API              | varies         |

For example, a view with `content_type: "diff"` on a PR repository produces files like `42_Add_login_endpoint_diff.md` containing the unified diff, ready for code review.

## Syncing

Source views are materialized — Airstore executes the query once and caches the results so reads are fast. To pick up new data from the source, you sync the view.

**From the dashboard:** Click the **Sync** button in the toolbar when viewing a source view.

**From the SDK:**

```typescript theme={null}
const result = await airstore.views.sync('ws_abc123', 'view_abc')
console.log(`${result.results_count} total, ${result.new_results} new`)
```

Syncing re-executes the view's query against the live source API and updates the cached files. It's idempotent — safe to call as often as you need.

### When to sync

* After you know the source data has changed (e.g., new PRs were opened)
* On a schedule in your backend automation
* Before a critical read where freshness matters

Views also sync automatically in the background on a periodic basis, so most of the time you don't need to trigger it manually.

## File structure

Each source view maps to a directory under `/sources/<integration>/`:

```
~/airstore/
├── sources/
│   ├── github/
│   │   └── open-prs/           # Source view
│   │       ├── 42_Add_login_endpoint_diff.md
│   │       └── 38_Fix_rate_limiter_diff.md
│   ├── gmail/
│   │   └── investor-emails/    # Source view
│   │       ├── meeting_followup.eml
│   │       └── q4_report.eml
│   └── linear/
│       └── design-issues/      # Source view
│           ├── AGE-71_Spike_Figure_out_chat_UX.md
│           └── AGE-57_Table_layout_gets_cut_off.md
└── tools/
    └── ...
```

View names are converted to URL-safe slugs (e.g., "Open PRs" becomes `open-prs`).

## Output formats

| Format   | Description                                                    |
| -------- | -------------------------------------------------------------- |
| `folder` | Each result becomes a separate file in the directory (default) |
| `file`   | All results are aggregated into a single file                  |

The `file` format is useful when you want a single document — for example, a sprint summary or a combined report. You can also specify a `fileExt` (e.g., `.md`) to control the output extension.

## Next steps

<CardGroup cols={2}>
  <Card title="Mounting" icon="hard-drive" href="/concepts/mounting">
    Mount Airstore and access your source views as local files.
  </Card>

  <Card title="TypeScript SDK" icon="code" href="/sdk/guides/source-views">
    Create and manage source views programmatically.
  </Card>
</CardGroup>
