ithura
v1.0.0
Published
Official TypeScript and JavaScript client for the Ithura API. Tasks, sprints, projects, modules, wiki pages, and webhooks for the quiet project management workspace.
Maintainers
Readme
ithura
Official TypeScript and JavaScript client for Ithura, a quiet project management workspace for deliberate teams: tasks, sprints, wiki, whiteboards, and intake.
Zero dependencies. Works in Node 18+, Bun, Deno, Cloudflare Workers, and the
browser (anywhere fetch exists).
Install
npm install ithuraQuick start
import { Ithura } from "ithura";
const ithura = new Ithura({ token: process.env.ITHURA_TOKEN! });
const workspace = ithura.workspace("acme");
const projects = await workspace.listProjects();
const project = workspace.project(projects[0].id);
// Create a task
const task = await project.createIssue({
name: "Login times out on slow connections",
priority: "high",
});
// Move it into the current sprint
const [sprint] = await project.listCycles();
await project.updateIssue(task.id, { cycle_id: sprint.id });
// Comment on it
await project.addComment(task.id, { comment_html: "<p>Reproduced on staging.</p>" });Get a token from Settings > API tokens in your workspace. It carries the permissions of the member who created it.
API
The client mirrors the published OpenAPI spec, so every method maps to a documented endpoint.
const ithura = new Ithura({ token });
await ithura.me();
await ithura.listWorkspaces();
const ws = ithura.workspace("acme");
await ws.get();
await ws.members();
await ws.listProjects();
await ws.createProject({ name: "Web", identifier: "WEB" });
await ws.listPages();
await ws.listViews();
await ws.listWebhooks();
await ws.createWebhook({ url: "https://example.com/hook", ... });
const p = ws.project(projectId);
await p.get();
await p.update({ name: "Web app" });
await p.states();
await p.labels();
await p.createLabel({ name: "regression", color: "#8a4f6d" });
await p.listIssues({ priority: "urgent", limit: 20 });
await p.getIssue(id);
await p.createIssue({ name: "..." });
await p.updateIssue(id, { state_id });
await p.deleteIssue(id);
await p.listComments(id);
await p.addComment(id, { comment_html: "<p>hi</p>" });
await p.issueActivities(id);
await p.listCycles(); // sprints
await p.createCycle({ name: "Sprint 21" });
await p.listModules();
await p.listBoards();
await p.listIntakes();Anything not covered
request() is the escape hatch, with the auth and error handling applied:
await ithura.request("GET", "/workspaces/acme/projects/", { query: { limit: 5 } });Errors
Non-2xx responses throw IthuraError with the status and parsed body:
import { IthuraError } from "ithura";
try {
await project.getIssue("missing");
} catch (err) {
if (err instanceof IthuraError && err.status === 404) {
// ...
}
}Self-hosting
new Ithura({ token, baseUrl: "https://ithura.internal" });A note on naming
The HTTP API's noun for a work item is issue, and the product calls them
tasks. Method names follow the API so the mapping to the spec stays
obvious. The same applies to cycle, which the product calls a sprint.
Links
- Ithura: https://ithura.com
- Documentation: https://ithura.com/docs
- MCP server for AI agents:
ithura-mcp
License
MIT
