DeepSeek Harness Remote
DeepSeek Harness Remote: DeepSeek Harness 실행 PC와 모바일·PC를 안전하게 연결해 어디서나 작업 이어받기
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기AI opportunity tracker for Gmail: finds opportunities and deadlines with an explainable match % (Next.js, Django, Gemini)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗An AI agent that reads your Gmail (read-only), finds internships, jobs, hackathons, scholarships and events, tracks their deadlines and ranks them against your profile, so nothing important gets buried in your inbox.
Live site: https://oppora-app.vercel.app
Try it without Gmail: on the live site, click Try the demo. It opens a shared, read-only sample account ("Alex") filled with made-up emails, so no sign-in or Gmail is needed and nothing you do there is saved. The first load may take about a minute while the free server wakes up.
Gmail sign-in is invite-only for now (Google's testing phase), so the demo is the way in for visitors.
▶ Watch on YouTube: a one-minute explainer of how Oppora finds opportunities in Gmail, ranks them and tracks their deadlines.
| Landing page: Sign in with Google or Try the demo | Opportunities found in the inbox, with match % |
| Details: AI summary and why it matches | Deadlines, coloured by urgency |
| AI insights and application progress | Assistant that answers from your own data |
On a phone:
All screenshots are from the public demo account, which contains only made-up sample emails.
| Part | Built with | Hosted on (free plans) |
|---|---|---|
| Website | Next.js 16 (App Router), React, TypeScript, Tailwind CSS v4, Radix, Lucide | Vercel |
| API | Python 3.14, Django 5.2, Django REST Framework, gunicorn | Render |
| Database | PostgreSQL 16 | Neon |
| Rate limits | Redis 7 | Upstash |
| AI | Google Gemini (free tier) behind one provider interface | Google AI Studio |
Gmail API (gmail.readonly) with Google sign-in (OAuth + PKCE) | Google Cloud | |
| Background work | Celery + Redis locally; on the free plan, short resumable batches and an hourly GitHub Actions scheduler | GitHub |
flowchart LR
B[Browser] --> V["Vercel<br/>Next.js website"]
V -- "/api/* (same-origin proxy)" --> R["Render<br/>Django + DRF API"]
R --> N[("Neon<br/>PostgreSQL")]
R --> U[("Upstash<br/>Redis rate limits")]
R <--> GM["Gmail API<br/>read-only"]
R --> GE["Google Gemini<br/>AI extraction"]
GH["GitHub Actions<br/>hourly scheduler"] -- "secret-protected POST" --> R
The browser only ever talks to the website. Next.js forwards /api/* to Django, so the session cookie is
first-party and httpOnly, no CORS is needed, and no key ever reaches the browser.
gmail.readonly scope is requested. Google sign-in uses PKCE, OAuth
tokens are encrypted at rest (Fernet, with key rotation) and never sent to the browser, and disconnecting revokes
access at Google.null and shows
as Not mentioned in email.More detail on each of these: CLAUDE.md (decisions and stage notes) and backend/README.md (API and backend layout).
.env locally, the hosting dashboards online). The browser bundle contains no
keys.TOKEN_ENCRYPTION_KEY=<new>,<old>, run
backend\.venv\Scripts\python backend\manage.py rotate_token_key, then remove the old key.I built Oppora with Claude Code as my AI pair-programmer, in 12 stages: I wrote the product brief and design direction, set the rules (read-only Gmail, never invent facts, free services only, tests for every stage), made the decisions at each step, and reviewed and tested the results, including with my own real Gmail before going live.
Free hosting guide (Vercel, Render, Neon, Upstash, GitHub Actions): docs/deploy.md. Google sign-in, Gmail and Gemini setup: docs/google-cloud-setup.md. A click-by-click 2-minute demo script: docs/demo-script.md.
In PowerShell, from the project folder:
powershell -ExecutionPolicy Bypass -File .\start-oppora.ps1
The script:
.env on the first run and generates any missing secret keysnpm install (first run, or when package-lock.json changes)docker compose up -d --wait)It's safe to run again: anything already running is left alone, except that the backend restarts when .env changed, and the worker and beat restart when .env or backend code changed. -ExecutionPolicy Bypass applies only to this run.
| Option | What it does |
|---|---|
-RefreshDemo | Reloads the demo account's data for today (dates are relative to the load day). Your real account isn't touched. |
-Restart | Restarts Oppora's own servers (never other programs on ports 8000/3000). |
-NoBrowser | Doesn't open the browser. |
Stop: close the four Oppora … windows. To stop the database too, run docker compose stop.
.env, and save. The backend restarts by itself, and Google sign-in then replaces the demo sign-in.cp .env.example .env # then fill in DJANGO_SECRET_KEY and TOKEN_ENCRYPTION_KEY (see the comments)
docker compose up -d --wait # Postgres + Redis
cd backend
python3.14 -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt -r requirements-dev.txt
python manage.py migrate
python manage.py seed_demo # demo account; needs Node and `npm install` in ../frontend
# four terminals:
python manage.py runserver 127.0.0.1:8000
python -m celery -A config worker --pool=solo --loglevel=info
python -m celery -A config beat --loglevel=info --schedule .celery/beat-schedule
cd ../frontend && npm install && npm run dev # http://localhost:3000
Without Redis or a worker you can set JOBS_BACKEND=thread. Syncs then run inside the web process, but nothing is scheduled.
Every variable is listed and explained in .env.example. The ones you'll touch:
| Variable | Purpose |
|---|---|
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URI | Google sign-in and Gmail (read-only). Keep the Google Cloud app in Testing mode with your Gmail as a test user. |
GEMINI_API_KEY, GEMINI_MODEL, GEMINI_FALLBACK_MODEL | The AI. Use a Google AI Studio project without billing so it stays free. |
AI_REQUESTS_PER_MINUTE, AI_REQUESTS_PER_DAY | Keep at or below your free-tier limits. Over the limit, emails wait in a queue and resume by themselves. |
GMAIL_INITIAL_SYNC_DAYS | How far back the first scan looks (default 60 days). |
DEFAULT_USER_TIMEZONE | Used for "today" until the browser reports your zone. |
TOKEN_ENCRYPTION_KEY, DJANGO_SECRET_KEY | Generated by the start script. Never commit them. |
AI_PROVIDER=openai switches to OpenAI, which is paid. It's never enabled by default.
cd frontend; npm run check # ESLint + TypeScript + Vitest
npm run build # production build
cd ..\backend; .venv\Scripts\python -m pytest # API, pipeline, security, journey, performance
.venv\Scripts\ruff check .; .venv\Scripts\ruff format --check .
.venv\Scripts\python manage.py makemigrations --check --dry-run
backend/tests/test_journey.py runs the complete journey with Google, Gmail and the AI faked: sign-in → sync → AI analysis → details → save → apply → reminder → assistant.
| Symptom | Fix |
|---|---|
| Sign in with Google opens the demo account | Google keys aren't in .env yet, or the backend wasn't restarted. Saving .env restarts it; -Restart forces it. |
| Settings shows Gmail: Needs reconnect | In Testing mode Google expires refresh tokens after 7 days. Click Reconnect. |
| The sync card says N emails queued | The AI's daily free limit is used up. They resume by themselves after the reset (midnight Pacific time) while the worker and beat are running. |
| Port 8000 or 3000 is in use | Another program uses it. The script tells you which. Close it, or change the port. |
| Demo dates look old | Run start-oppora.ps1 -RefreshDemo. |
DJANGO_DEBUG=false, strong secrets (the server refuses to start with weak or missing keys) and its own database
password on Neon.