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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@
All notable changes to TokenFlow are recorded here. Versions follow
[semantic versioning](https://semver.org/spec/v2.0.0.html).

## 1.3.5 — 2026-09-14

No change to how TokenFlow reads or prices anything. One test-suite defect and two
documentation corrections.

### Fixed

- **`npm test` no longer fails on a Mac without Xcode.** The app-bundle suite skipped when
`swiftc` was absent, which is not the condition that matters: the Command Line Tools ship
`swiftc` but not SwiftUI's macro plugins, so `@State` never expands and every view in
`main.swift` collapses into errors about assigning to an immutable `self`. Three tests
failed, and the failure read as a defect in the menu bar app rather than a missing toolchain.
The probe now compiles the smallest view that needs the plugin, and the skip message names
Xcode. The shipped app is unaffected: CI builds it on a runner with the full toolchain.

### Docs

- **The test count reads 841**, which is what the suite has. The README said 836.
- **The README's link row no longer prints half the Homebrew command.** `brew install --cask
tokenflow` on its own fails, because the cask lives in this repo's own tap and the tap
command has to come first. The row now points at the Install section, which carries both
lines.

## 1.3.4 — 2026-09-07

Interface fixes only; nothing about how TokenFlow reads or prices usage changes. Every one of
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ per-source and per-model usage, capacity meters and forecast, in light and dark.
 · 
📦 <a href="https://www.npmjs.com/package/@vimoxshah/tokenflow"><code>@vimoxshah/tokenflow</code> on npm</a>
&nbsp;·&nbsp;
🍺 <code>brew install --cask tokenflow</code> (via <a href="https://github.com/vimoxshah/tokenflow">this tap</a>)
🍺 <a href="#install"><strong>Homebrew</strong></a> <em>(tap, then cask)</em>
</p>

**How deep it goes**
Expand All @@ -62,7 +62,7 @@ per-source and per-model usage, capacity meters and forecast, in light and dark.
| **Analytics** | 21 views: overview KPIs with a story strip, receipts per branch and pull request, cost per ticket, session anatomy, live, composition, provider/model intelligence, interfaces, hour×weekday heatmap + calendar, peaks, efficiency ratios, cache health, cost with coverage, model what-if, git correlations (labelled), rhythm and focus, period compare, compare branches, searchable data explorer, annotations, per-field data health |
| **Integrations** | A GitHub Action and a **self-hosted GitHub App** (your App, your server, our code) that put a receipt comment and a budget check run on every pull request; receipts as git notes that travel with the code; an **MCP server** so the agent can read its own bill; a **FOCUS-shaped export** for a FinOps tool; **org policy** pulled from a team server you run |
| **Live mode** | Watcher daemon, native Swift menu bar app (live sessions, today's receipts, guard state, provider/source/model breakdowns, capacity meters with reset countdowns & ETAs, forecast with stated confidence, MAD-based anomaly alerts, per-source sparklines, appearance toggle), SwiftBar/xbar plugin |
| **Engineering** | Zero runtime dependencies · 836 tests · lint invariants (e.g. "no `\|\| 0` on a token field") · tsc-clean JSDoc types · CI on macOS/Linux/Windows × Node 22/24 |
| **Engineering** | Zero runtime dependencies · 841 tests · lint invariants (e.g. "no `\|\| 0` on a token field") · tsc-clean JSDoc types · CI on macOS/Linux/Windows × Node 22/24 |

Zero runtime dependencies. Nothing leaves your machine. No API keys, no accounts, no telemetry.

Expand Down Expand Up @@ -332,7 +332,7 @@ from `file://` with no server. A full CSV export doubles as a portable dataset:
## Contributing

```bash
npm test # 836 tests: normalization, adapters, analytics, store, receipts, guard
npm test # 841 tests: normalization, adapters, analytics, store, receipts, guard
npm run lint # project invariants (incl. "no || 0 on a token field")
npm run typecheck # tsc over JSDoc types — must be zero errors
npm run validate # self-check: runtime, adapters, store↔cube agreement
Expand Down
2 changes: 1 addition & 1 deletion action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # notes live outside the default shallow fetch
- uses: vimoxshah/tokenflow@v1.3.4
- uses: vimoxshah/tokenflow@v1.3.5
# or, dogfooding this repo's own checkout: uses: ./
with:
token: ${{ secrets.GITHUB_TOKEN }} # default; only pass to override
Expand Down
2 changes: 1 addition & 1 deletion docs/receipts-on-github.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ network call.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # notes live outside the default shallow fetch
- uses: vimoxshah/tokenflow@v1.3.4
- uses: vimoxshah/tokenflow@v1.3.5
with:
max-usd: '50'
max-usd-per-100-lines: '5'
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vimoxshah/tokenflow",
"version": "1.3.4",
"version": "1.3.5",
"description": "Local-first, provider-agnostic analytics for the AI tokens you actually spend. Zero dependencies, nothing leaves your machine.",
"type": "module",
"license": "MIT",
Expand Down
18 changes: 14 additions & 4 deletions test/bundle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,32 @@ import { execFileSync } from 'node:child_process';
* had a menu bar app with nothing to drive. Both are build-script properties,
* invisible to every other test, and only a real build can prove them.
*
* Building takes swiftc, so this suite skips anywhere it cannot run: off
* macOS, or on a macOS box without the Command Line Tools.
* Building takes a toolchain that can compile SwiftUI, so this suite skips
* anywhere it cannot run. `swiftc --version` is not that test: the Command Line
* Tools ship swiftc but not SwiftUI's macro plugins, so on a Mac with no Xcode
* `@State` fails to expand and every view in main.swift collapses into errors
* about assigning to an immutable self. That reads as a product defect and is
* not one, so the probe below compiles the smallest thing that needs the
* plugin and skips when it cannot.
*/
const REPO = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..');

function canBuild() {
if (process.platform !== 'darwin') return false;
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'tf-swift-probe-'));
const file = path.join(dir, 'probe.swift');
try {
execFileSync('swiftc', ['--version'], { stdio: 'ignore', timeout: 20000 });
fs.writeFileSync(file, 'import SwiftUI\nstruct P: View { @State private var x = 0\n var body: some View { Color.clear.onHover { _ in x = 1 } } }\n');
execFileSync('swiftc', ['-typecheck', file], { stdio: 'ignore', timeout: 120000 });
return true;
} catch {
return false;
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}
}

const skip = canBuild() ? false : 'needs macOS with swiftc';
const skip = canBuild() ? false : 'needs macOS with a toolchain that can compile SwiftUI (Xcode, not the Command Line Tools alone)';

function build(outDir, { portable }) {
execFileSync('bash', [path.join(REPO, 'scripts', 'build-menubar-app.sh'), outDir], {
Expand Down
Loading