Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Aether Agent configuration (all optional — sensible defaults ship in-app).
# Copy to .env only if you need to override. NEVER commit a real token.

# Aether API base URL. Default: https://api.aethersystems.net
# AETHER_BASE_URL=https://api.aethersystems.net
# Aether API base URL. Default: https://api.aethersystems.net/cloud
# AETHER_BASE_URL=https://api.aethersystems.net/cloud

# Page `aether login` opens. Default: https://aethersystems.net/platform
# AETHER_LOGIN_URL=https://aethersystems.net/platform
Expand Down
22 changes: 22 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: '06:00'
timezone: America/New_York
open-pull-requests-limit: 5
groups:
development-toolchain:
dependency-type: development

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: '06:15'
timezone: America/New_York
open-pull-requests-limit: 5
58 changes: 52 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@ name: CI
on:
push:
branches:
- '**'
- main
pull_request:
branches:
- main
workflow_dispatch:

permissions:
contents: read

# Same-repo PR branches fire both on.push and on.pull_request for the same
# commit, running build-and-test twice. Cancel the superseded run instead of
# paying for (and status-checking) both.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-and-test:
runs-on: ubuntu-latest
name: Test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-latest
runs-on: ${{ matrix.os }}
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
Expand All @@ -31,7 +42,42 @@ jobs:
cache: 'npm'

- name: Install dependencies
run: npm ci
run: npm ci --ignore-scripts

- name: Build and test
run: npm test

supply-chain:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: 'npm'

- name: Install dependencies without lifecycle scripts
run: npm ci --ignore-scripts

- name: Audit dependencies
run: npm audit --audit-level=high

- name: Verify production package and policy
run: npm run verify:production

- name: Generate CycloneDX SBOM
run: npm sbom --sbom-format cyclonedx > aether-agents.cdx.json

- name: Upload SBOM
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: aether-agents-sbom-${{ github.sha }}
path: aether-agents.cdx.json
if-no-files-found: error
retention-days: 90
42 changes: 42 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: CodeQL

on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: '17 6 * * 1'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
packages: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Initialize CodeQL
uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
with:
languages: javascript-typescript
build-mode: none

- name: Analyze
uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4.37.1
103 changes: 103 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Release npm package

on:
release:
types:
- published

permissions:
contents: read

concurrency:
group: npm-production-${{ github.event.release.tag_name }}
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 25
environment: npm-production
permissions:
contents: read
id-token: write
attestations: write
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
steps:
- name: Checkout immutable release tag
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ env.RELEASE_TAG }}
fetch-depth: 0
persist-credentials: false

- name: Verify release commit belongs to main
shell: bash
run: |
git fetch --no-tags origin main
git merge-base --is-ancestor HEAD origin/main

- name: Set up Node.js and npm registry
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: 'npm'
registry-url: https://registry.npmjs.org

- name: Install dependencies without lifecycle scripts
run: npm ci --ignore-scripts

- name: Audit dependencies
run: npm audit --audit-level=high

- name: Test release source
run: npm test

- name: Verify tag, production policy, and package allowlist
run: npm run verify:production -- --tag "$RELEASE_TAG"

- name: Generate CycloneDX SBOM
run: npm sbom --sbom-format cyclonedx > aether-agents.cdx.json

- name: Build immutable npm tarball
id: pack
shell: bash
run: |
npm pack --json --ignore-scripts > pack-metadata.json
tarball="$(node -e "const fs=require('node:fs');const p=JSON.parse(fs.readFileSync('pack-metadata.json','utf8'));process.stdout.write(p[0].filename)")"
test -n "$tarball"
echo "tarball=$tarball" >> "$GITHUB_OUTPUT"

- name: Smoke-test exact tarball
shell: bash
run: |
prefix="$RUNNER_TEMP/aether-install"
npm install --global --prefix "$prefix" "${{ steps.pack.outputs.tarball }}" --ignore-scripts
test "$("$prefix/bin/aether" --version)" = "${RELEASE_TAG#v}"
"$prefix/bin/aether" --help > /dev/null

- name: Attest package provenance
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: ${{ steps.pack.outputs.tarball }}

- name: Upload release evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: npm-release-${{ env.RELEASE_TAG }}
path: |
${{ steps.pack.outputs.tarball }}
aether-agents.cdx.json
pack-metadata.json
if-no-files-found: error
retention-days: 90

- name: Require npm publishing credential
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: test -n "$NODE_AUTH_TOKEN"

- name: Publish verified tarball
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish "${{ steps.pack.outputs.tarball }}" --access public --provenance
2 changes: 1 addition & 1 deletion COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ Requires an active orchestrator — switch with `/agent neo` or `/agent kronus`

| Var | Default | Meaning |
|---|---|---|
| `AETHER_BASE_URL` | `https://api.aethersystems.net` | Overrides the config `baseUrl`. |
| `AETHER_BASE_URL` | `https://api.aethersystems.net/cloud` | Overrides the config `baseUrl`. |
| `AETHER_LOGIN_URL` | `https://aethersystems.net/platform` | Page `aether auth login` opens. |
| `AETHER_TOKEN` | *(unset)* | Inject a session token (CI / headless / embedding). |
| `AETHER_CONFIG_DIR` | `~/.config/aether` | Config + token + REPL-history directory. |
Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ cd aether-agent
npm install
npm run build
npm test
npm run verify:production
```

Node ≥ 24. Zero runtime dependencies — the client uses only Node built-ins, and
Expand Down Expand Up @@ -38,6 +39,8 @@ Most features touch a `core/` module + a `commands/` file.
tested — match that bar).
- **Types pass.** `npm run typecheck` uses the repository's pinned TypeScript 7
compiler and strict project settings.
- **Production policy passes.** `npm run verify:production` checks the npm
package allowlist, pinned CI actions, bounded jobs, and installer safety.
- **Types are honest.** No `any` in application code; narrow `unknown`.
- **Small files, one job each.** If a file grows past ~300 lines it's probably
doing too much.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

**Aether Agent is in beta.** Updates are shipping quickly.
```bash
npm i -g aether-agents # or run once: npx aether-agents
npm i -g aether-agents --ignore-scripts # or run once: npx --ignore-scripts aether-agents
```

[Install](#install-in-three-moves) · [Models & pricing](#models--pricing) · [Commands](#commands) · [Security](#security) · [Release notes](RELEASE_NOTES.md)
Expand All @@ -30,7 +30,7 @@ It scans, plans, edits, and runs your tests — in your repo, on your terms. Ver
</div>

```bash
npm i -g aether-agents # 01 — drop it in (Node ≥ 24)
npm i -g aether-agents --ignore-scripts # 01 — drop it in (Node ≥ 24)

aether auth login # 02 — sign in once
aether agent # …terminal opens. Just start chatting.
Expand All @@ -41,7 +41,7 @@ aether agent --local # …same terminal, nothing leaves the machi

`aether agent` opens the REPL — chat with the model, slash-commands at hand, the agent edits files and runs your tests **in the same session**. Both brains run through the same host loop, render, tools, and commands — switching just swaps the transport. On the hosted path your code stays local and only the prompt + context you send leaves; on `--local`, nothing leaves at all. The local brain runs on **[Unlimited Context](https://github.com/DBarr3/Unlimited-Context-LLM)** — Aether's open-source (Apache-2.0) memory engine that gives any Ollama model a billion-token working memory.

> Prefer a script? `curl -fsSL https://aethersystems.net/install.sh | sh` (macOS / Linux / WSL) · `irm https://aethersystems.net/install.ps1 | iex` (Windows PowerShell). Both just verify Node and run the npm install — no native deps, no daemon.
> Prefer the installer UI? Download [`install.sh`](install.sh) or [`install.ps1`](install.ps1), inspect it, then run it locally. Set `AETHER_VERSION=0.1.0` (shell) or `-Version 0.1.0` (PowerShell) to pin an exact release. The canonical npm command above verifies registry integrity and disables lifecycle scripts; there are no native or runtime dependencies and no daemon.

## Models & pricing

Expand Down
17 changes: 17 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,20 @@ Out of scope here (report to Aether AI directly, same address):
- Rotate your CLI token at [aethersystems.net/platform](https://aethersystems.net/platform)
if you suspect it leaked, then `aether auth logout` and `aether auth login` again.
- Prefer `aether login` (browser) over pasting long-lived tokens into scripts.

## Release and supply-chain controls

- GitHub Actions are pinned to immutable commit SHAs and run with explicit,
least-privilege permissions and bounded timeouts.
- CI installs dependencies with lifecycle scripts disabled, audits the complete
development graph, tests on Linux and Windows, verifies the npm package
allowlist, and emits a CycloneDX SBOM.
- npm publication accepts only a `v<package-version>` tag, runs through the
protected `npm-production` environment, attests the tarball, and publishes
it with npm provenance. A release never rebuilds after the verified tarball
has been created.
- Installer scripts support exact-version pinning and never recommend piping a
network response directly into a shell.

Operational setup, rollback, secret rotation, and evidence retention are
documented in [`docs/PRODUCTION_OPERATIONS.md`](docs/PRODUCTION_OPERATIONS.md).
Loading